Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rtl871x_ioctl_linux.c
Go to the documentation of this file.
1 /******************************************************************************
2  * rtl871x_ioctl_linux.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 <[email protected]>
25  * Larry Finger <[email protected]>
26  *
27  ******************************************************************************/
28 
29 #define _RTL871X_IOCTL_LINUX_C_
30 #define _RTL871X_MP_IOCTL_C_
31 
32 #include "osdep_service.h"
33 #include "drv_types.h"
34 #include "wlan_bssdef.h"
35 #include "rtl871x_debug.h"
36 #include "wifi.h"
37 #include "rtl871x_mlme.h"
38 #include "rtl871x_ioctl.h"
39 #include "rtl871x_ioctl_set.h"
40 #include "rtl871x_mp_ioctl.h"
41 #include "mlme_osdep.h"
42 #include <linux/wireless.h>
43 #include <linux/module.h>
44 #include <linux/kernel.h>
45 #include <linux/init.h>
46 #include <linux/io.h>
47 #include <linux/semaphore.h>
48 #include <net/iw_handler.h>
49 #include <linux/if_arp.h>
50 
51 #define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 0x1E)
52 
53 #define SCAN_ITEM_SIZE 768
54 #define MAX_CUSTOM_LEN 64
55 #define RATE_COUNT 4
56 
57 
58 static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
59  6000000, 9000000, 12000000, 18000000,
60  24000000, 36000000, 48000000, 54000000};
61 
62 static const long ieee80211_wlan_frequencies[] = {
63  2412, 2417, 2422, 2427,
64  2432, 2437, 2442, 2447,
65  2452, 2457, 2462, 2467,
66  2472, 2484
67 };
68 
69 static const char * const iw_operation_mode[] = {
70  "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary",
71  "Monitor"
72 };
73 
80 static int hwaddr_aton_i(const char *txt, u8 *addr)
81 {
82  int i;
83 
84  for (i = 0; i < 6; i++) {
85  int a, b;
86 
87  a = hex_to_bin(*txt++);
88  if (a < 0)
89  return -1;
90  b = hex_to_bin(*txt++);
91  if (b < 0)
92  return -1;
93  *addr++ = (a << 4) | b;
94  if (i < 5 && *txt++ != ':')
95  return -1;
96  }
97  return 0;
98 }
99 
101 {
102  union iwreq_data wrqu;
103  struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
104 
105  wrqu.ap_addr.sa_family = ARPHRD_ETHER;
106  memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress,
107  ETH_ALEN);
108  wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
109 }
110 
112 {
113  union iwreq_data wrqu;
114 
115  wrqu.ap_addr.sa_family = ARPHRD_ETHER;
116  memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
117  wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
118 }
119 
120 static inline void handle_pairwise_key(struct sta_info *psta,
121  struct ieee_param *param,
122  struct _adapter *padapter)
123 {
124  /* pairwise key */
125  memcpy(psta->x_UncstKey.skey, param->u.crypt.key,
126  (param->u.crypt. key_len > 16 ? 16 : param->u.crypt.key_len));
127  if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
128  memcpy(psta->tkiptxmickey. skey, &(param->u.crypt.
129  key[16]), 8);
130  memcpy(psta->tkiprxmickey. skey, &(param->u.crypt.
131  key[24]), 8);
132  padapter->securitypriv. busetkipkey = false;
133  _set_timer(&padapter->securitypriv.tkip_timer, 50);
134  }
135  r8712_setstakey_cmd(padapter, (unsigned char *)psta, true);
136 }
137 
138 static inline void handle_group_key(struct ieee_param *param,
139  struct _adapter *padapter)
140 {
141  if (0 < param->u.crypt.idx &&
142  param->u.crypt.idx < 3) {
143  /* group key idx is 1 or 2 */
144  memcpy(padapter->securitypriv.XGrpKey[param->u.crypt.
145  idx-1].skey, param->u.crypt.key, (param->u.crypt.key_len
146  > 16 ? 16 : param->u.crypt.key_len));
147  memcpy(padapter->securitypriv.XGrptxmickey[param->
148  u.crypt.idx-1].skey, &(param->u.crypt.key[16]), 8);
149  memcpy(padapter->securitypriv. XGrprxmickey[param->
150  u.crypt.idx-1].skey, &(param->u.crypt.key[24]), 8);
151  padapter->securitypriv.binstallGrpkey = true;
152  r8712_set_key(padapter, &padapter->securitypriv,
153  param->u.crypt.idx);
154  if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
155  if (padapter->registrypriv.power_mgnt != padapter->
156  pwrctrlpriv.pwr_mode)
157  _set_timer(&(padapter->mlmepriv.dhcp_timer),
158  60000);
159  }
160  }
161 }
162 
163 static inline char *translate_scan(struct _adapter *padapter,
164  struct iw_request_info *info,
165  struct wlan_network *pnetwork,
166  char *start, char *stop)
167 {
168  struct iw_event iwe;
169  struct ieee80211_ht_cap *pht_capie;
170  char *current_val;
171  s8 *p;
172  u32 i = 0, ht_ielen = 0;
173  u16 cap, ht_cap = false, mcs_rate;
174  u8 rssi, bw_40MHz = 0, short_GI = 0;
175 
176  if ((pnetwork->network.Configuration.DSConfig < 1) ||
177  (pnetwork->network.Configuration.DSConfig > 14)) {
178  if (pnetwork->network.Configuration.DSConfig < 1)
179  pnetwork->network.Configuration.DSConfig = 1;
180  else
181  pnetwork->network.Configuration.DSConfig = 14;
182  }
183  /* AP MAC address */
184  iwe.cmd = SIOCGIWAP;
185  iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
186  memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
187  start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
188  /* Add the ESSID */
189  iwe.cmd = SIOCGIWESSID;
190  iwe.u.data.flags = 1;
191  iwe.u.data.length = (u16)min((u16)pnetwork->network.Ssid.SsidLength,
192  (u16)32);
193  start = iwe_stream_add_point(info, start, stop, &iwe,
194  pnetwork->network.Ssid.Ssid);
195  /* parsing HT_CAP_IE */
196  p = r8712_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_,
197  &ht_ielen, pnetwork->network.IELength - 12);
198  if (p && ht_ielen > 0) {
199  ht_cap = true;
200  pht_capie = (struct ieee80211_ht_cap *)(p + 2);
201  memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
202  bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH)
203  ? 1 : 0;
204  short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20 |
205  IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
206  }
207  /* Add the protocol name */
208  iwe.cmd = SIOCGIWNAME;
209  if ((r8712_is_cckratesonly_included((u8 *)&pnetwork->network.
210  SupportedRates)) == true) {
211  if (ht_cap == true)
212  snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
213  else
214  snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
215  } else if ((r8712_is_cckrates_included((u8 *)&pnetwork->network.
216  SupportedRates)) == true) {
217  if (ht_cap == true)
218  snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
219  else
220  snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
221  } else {
222  if (ht_cap == true)
223  snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
224  else
225  snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
226  }
227  start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
228  /* Add mode */
229  iwe.cmd = SIOCGIWMODE;
230  memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs),
231  2);
232  cap = le16_to_cpu(cap);
234  if (cap & WLAN_CAPABILITY_BSS)
235  iwe.u.mode = (u32)IW_MODE_MASTER;
236  else
237  iwe.u.mode = (u32)IW_MODE_ADHOC;
238  start = iwe_stream_add_event(info, start, stop, &iwe,
240  }
241  /* Add frequency/channel */
242  iwe.cmd = SIOCGIWFREQ;
243  {
244  /* check legal index */
245  u8 dsconfig = pnetwork->network.Configuration.DSConfig;
246  if (dsconfig >= 1 && dsconfig <= sizeof(
247  ieee80211_wlan_frequencies) / sizeof(long))
248  iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[
249  pnetwork->network.Configuration.
250  DSConfig - 1] * 100000);
251  else
252  iwe.u.freq.m = 0;
253  }
254  iwe.u.freq.e = (s16)1;
255  iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
256  start = iwe_stream_add_event(info, start, stop, &iwe,
258  /* Add encryption capability */
259  iwe.cmd = SIOCGIWENCODE;
260  if (cap & WLAN_CAPABILITY_PRIVACY)
261  iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED |
263  else
264  iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
265  iwe.u.data.length = (u16)0;
266  start = iwe_stream_add_point(info, start, stop, &iwe,
267  pnetwork->network.Ssid.Ssid);
268  /*Add basic and extended rates */
269  current_val = start + iwe_stream_lcp_len(info);
270  iwe.cmd = SIOCGIWRATE;
271  iwe.u.bitrate.fixed = 0;
272  iwe.u.bitrate.disabled = 0;
273  iwe.u.bitrate.value = 0;
274  i = 0;
275  while (pnetwork->network.SupportedRates[i] != 0) {
276  /* Bit rate given in 500 kb/s units */
277  iwe.u.bitrate.value = (pnetwork->network.SupportedRates[i++] &
278  0x7F) * 500000;
279  current_val = iwe_stream_add_value(info, start, current_val,
280  stop, &iwe, IW_EV_PARAM_LEN);
281  }
282  /* Check if we added any event */
283  if ((current_val - start) > iwe_stream_lcp_len(info))
284  start = current_val;
285  /* parsing WPA/WPA2 IE */
286  {
288  u8 wpa_ie[255], rsn_ie[255];
289  u16 wpa_len = 0, rsn_len = 0;
290  int n;
291  sint out_len = 0;
292  out_len = r8712_get_sec_ie(pnetwork->network.IEs,
293  pnetwork->network.
294  IELength, rsn_ie, &rsn_len,
295  wpa_ie, &wpa_len);
296  if (wpa_len > 0) {
297  memset(buf, 0, MAX_WPA_IE_LEN);
298  n = sprintf(buf, "wpa_ie=");
299  for (i = 0; i < wpa_len; i++) {
300  n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
301  "%02x", wpa_ie[i]);
302  if (n >= MAX_WPA_IE_LEN)
303  break;
304  }
305  memset(&iwe, 0, sizeof(iwe));
306  iwe.cmd = IWEVCUSTOM;
307  iwe.u.data.length = (u16)strlen(buf);
308  start = iwe_stream_add_point(info, start, stop,
309  &iwe, buf);
310  memset(&iwe, 0, sizeof(iwe));
311  iwe.cmd = IWEVGENIE;
312  iwe.u.data.length = (u16)wpa_len;
313  start = iwe_stream_add_point(info, start, stop,
314  &iwe, wpa_ie);
315  }
316  if (rsn_len > 0) {
317  memset(buf, 0, MAX_WPA_IE_LEN);
318  n = sprintf(buf, "rsn_ie=");
319  for (i = 0; i < rsn_len; i++) {
320  n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
321  "%02x", rsn_ie[i]);
322  if (n >= MAX_WPA_IE_LEN)
323  break;
324  }
325  memset(&iwe, 0, sizeof(iwe));
326  iwe.cmd = IWEVCUSTOM;
327  iwe.u.data.length = strlen(buf);
328  start = iwe_stream_add_point(info, start, stop,
329  &iwe, buf);
330  memset(&iwe, 0, sizeof(iwe));
331  iwe.cmd = IWEVGENIE;
332  iwe.u.data.length = rsn_len;
333  start = iwe_stream_add_point(info, start, stop, &iwe,
334  rsn_ie);
335  }
336  }
337 
338  { /* parsing WPS IE */
339  u8 wps_ie[512];
340  uint wps_ielen;
341 
342  if (r8712_get_wps_ie(pnetwork->network.IEs,
343  pnetwork->network.IELength,
344  wps_ie, &wps_ielen) == true) {
345  if (wps_ielen > 2) {
346  iwe.cmd = IWEVGENIE;
347  iwe.u.data.length = (u16)wps_ielen;
348  start = iwe_stream_add_point(info, start, stop,
349  &iwe, wps_ie);
350  }
351  }
352  }
353  /* Add quality statistics */
354  iwe.cmd = IWEVQUAL;
355  rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
356  /* we only update signal_level (signal strength) that is rssi. */
357  iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED |
359  iwe.u.qual.level = rssi; /* signal strength */
360  iwe.u.qual.qual = 0; /* signal quality */
361  iwe.u.qual.noise = 0; /* noise level */
362  start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
363  /* how to translate rssi to ?% */
364  return start;
365 }
366 
367 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
368 {
369  struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
370  int ret = 0;
371 
372  if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
373  padapter->securitypriv.ndisencryptstatus =
375  padapter->securitypriv.ndisauthtype =
377  padapter->securitypriv.AuthAlgrthm = 3;
378  } else if (value & AUTH_ALG_SHARED_KEY) {
379  padapter->securitypriv.ndisencryptstatus =
381  padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
382  padapter->securitypriv.AuthAlgrthm = 1;
383  } else if (value & AUTH_ALG_OPEN_SYSTEM) {
384  if (padapter->securitypriv.ndisauthtype <
386  padapter->securitypriv.ndisauthtype =
388  padapter->securitypriv.AuthAlgrthm = 0;
389  }
390  } else
391  ret = -EINVAL;
392  return ret;
393 }
394 
395 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
396  u32 param_len)
397 {
398  int ret = 0;
399  u32 wep_key_idx, wep_key_len = 0;
400  struct NDIS_802_11_WEP *pwep = NULL;
401  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
402  struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
403  struct security_priv *psecuritypriv = &padapter->securitypriv;
404 
405  param->u.crypt.err = 0;
406  param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
407  if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) +
408  param->u.crypt.key_len)
409  return -EINVAL;
410  if (is_broadcast_ether_addr(param->sta_addr)) {
411  if (param->u.crypt.idx >= WEP_KEYS) {
412  /* for large key indices, set the default (0) */
413  param->u.crypt.idx = 0;
414  }
415  } else
416  return -EINVAL;
417  if (strcmp(param->u.crypt.alg, "WEP") == 0) {
418  printk(KERN_INFO "r8712u: wpa_set_encryption, crypt.alg ="
419  " WEP\n");
420  padapter->securitypriv.ndisencryptstatus =
422  padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
423  padapter->securitypriv.XGrpPrivacy = _WEP40_;
424  wep_key_idx = param->u.crypt.idx;
425  wep_key_len = param->u.crypt.key_len;
426  if (wep_key_idx >= WEP_KEYS)
427  wep_key_idx = 0;
428  if (wep_key_len > 0) {
429  wep_key_len = wep_key_len <= 5 ? 5 : 13;
430  pwep = (struct NDIS_802_11_WEP *)_malloc((u32)
431  (wep_key_len +
433  KeyMaterial)));
434  if (pwep == NULL)
435  return -ENOMEM;
436  memset(pwep, 0, sizeof(struct NDIS_802_11_WEP));
437  pwep->KeyLength = wep_key_len;
438  pwep->Length = wep_key_len +
440  KeyMaterial);
441  if (wep_key_len == 13) {
442  padapter->securitypriv.PrivacyAlgrthm =
443  _WEP104_;
444  padapter->securitypriv.XGrpPrivacy =
445  _WEP104_;
446  }
447  } else
448  return -EINVAL;
449  pwep->KeyIndex = wep_key_idx;
450  pwep->KeyIndex |= 0x80000000;
451  memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
452  if (param->u.crypt.set_tx) {
453  if (r8712_set_802_11_add_wep(padapter, pwep) ==
454  (u8)_FAIL)
455  ret = -EOPNOTSUPP;
456  } else {
457  /* don't update "psecuritypriv->PrivacyAlgrthm" and
458  * "psecuritypriv->PrivacyKeyIndex=keyid", but can
459  * r8712_set_key to fw/cam
460  */
461  if (wep_key_idx >= WEP_KEYS) {
462  ret = -EOPNOTSUPP;
463  goto exit;
464  }
465  memcpy(&(psecuritypriv->DefKey[wep_key_idx].
466  skey[0]), pwep->KeyMaterial,
467  pwep->KeyLength);
468  psecuritypriv->DefKeylen[wep_key_idx] =
469  pwep->KeyLength;
470  r8712_set_key(padapter, psecuritypriv, wep_key_idx);
471  }
472  goto exit;
473  }
474  if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
475  struct sta_info *psta, *pbcmc_sta;
476  struct sta_priv *pstapriv = &padapter->stapriv;
477 
478  if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
479  WIFI_MP_STATE) == true) { /* sta mode */
480  psta = r8712_get_stainfo(pstapriv,
481  get_bssid(pmlmepriv));
482  if (psta) {
483  psta->ieee8021x_blocked = false;
484  if ((padapter->securitypriv.ndisencryptstatus ==
486  (padapter->securitypriv.ndisencryptstatus ==
488  psta->XPrivacy = padapter->
489  securitypriv.PrivacyAlgrthm;
490  if (param->u.crypt.set_tx == 1)
491  handle_pairwise_key(psta, param,
492  padapter);
493  else /* group key */
494  handle_group_key(param, padapter);
495  }
496  pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
497  if (pbcmc_sta) {
498  pbcmc_sta->ieee8021x_blocked = false;
499  if ((padapter->securitypriv.ndisencryptstatus ==
501  (padapter->securitypriv.ndisencryptstatus ==
503  pbcmc_sta->XPrivacy =
504  padapter->securitypriv.
505  PrivacyAlgrthm;
506  }
507  }
508  }
509 exit:
510  kfree((u8 *)pwep);
511  return ret;
512 }
513 
514 static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
515  unsigned short ielen)
516 {
517  u8 *buf = NULL, *pos = NULL;
518  int group_cipher = 0, pairwise_cipher = 0;
519  int ret = 0;
520 
521  if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL))
522  return -EINVAL;
523  if (ielen) {
524  buf = _malloc(ielen);
525  if (buf == NULL)
526  return -ENOMEM;
527  memcpy(buf, pie , ielen);
528  pos = buf;
529  if (ielen < RSN_HEADER_LEN) {
530  ret = -EINVAL;
531  goto exit;
532  }
533  if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
534  &pairwise_cipher) == _SUCCESS) {
535  padapter->securitypriv.AuthAlgrthm = 2;
536  padapter->securitypriv.ndisauthtype =
538  }
539  if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
540  &pairwise_cipher) == _SUCCESS) {
541  padapter->securitypriv.AuthAlgrthm = 2;
542  padapter->securitypriv.ndisauthtype =
543  Ndis802_11AuthModeWPA2PSK;
544  }
545  switch (group_cipher) {
546  case WPA_CIPHER_NONE:
547  padapter->securitypriv.XGrpPrivacy =
548  _NO_PRIVACY_;
549  padapter->securitypriv.ndisencryptstatus =
551  break;
552  case WPA_CIPHER_WEP40:
553  padapter->securitypriv.XGrpPrivacy = _WEP40_;
554  padapter->securitypriv.ndisencryptstatus =
556  break;
557  case WPA_CIPHER_TKIP:
558  padapter->securitypriv.XGrpPrivacy = _TKIP_;
559  padapter->securitypriv.ndisencryptstatus =
561  break;
562  case WPA_CIPHER_CCMP:
563  padapter->securitypriv.XGrpPrivacy = _AES_;
564  padapter->securitypriv.ndisencryptstatus =
566  break;
567  case WPA_CIPHER_WEP104:
568  padapter->securitypriv.XGrpPrivacy = _WEP104_;
569  padapter->securitypriv.ndisencryptstatus =
571  break;
572  }
573  switch (pairwise_cipher) {
574  case WPA_CIPHER_NONE:
575  padapter->securitypriv.PrivacyAlgrthm =
576  _NO_PRIVACY_;
577  padapter->securitypriv.ndisencryptstatus =
579  break;
580  case WPA_CIPHER_WEP40:
581  padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
582  padapter->securitypriv.ndisencryptstatus =
584  break;
585  case WPA_CIPHER_TKIP:
586  padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
587  padapter->securitypriv.ndisencryptstatus =
589  break;
590  case WPA_CIPHER_CCMP:
591  padapter->securitypriv.PrivacyAlgrthm = _AES_;
592  padapter->securitypriv.ndisencryptstatus =
594  break;
595  case WPA_CIPHER_WEP104:
596  padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
597  padapter->securitypriv.ndisencryptstatus =
599  break;
600  }
601  padapter->securitypriv.wps_phase = false;
602  {/* set wps_ie */
603  u16 cnt = 0;
604  u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
605 
606  while (cnt < ielen) {
607  eid = buf[cnt];
608 
609  if ((eid == _VENDOR_SPECIFIC_IE_) &&
610  (!memcmp(&buf[cnt+2], wps_oui, 4))) {
611  printk(KERN_INFO "r8712u: "
612  "SET WPS_IE\n");
613  padapter->securitypriv.wps_ie_len =
614  ((buf[cnt+1] + 2) <
615  (MAX_WPA_IE_LEN << 2)) ?
616  (buf[cnt + 1] + 2) :
617  (MAX_WPA_IE_LEN << 2);
618  memcpy(padapter->securitypriv.wps_ie,
619  &buf[cnt],
620  padapter->securitypriv.wps_ie_len);
621  padapter->securitypriv.wps_phase =
622  true;
623  printk(KERN_INFO "r8712u: SET WPS_IE,"
624  " wps_phase==true\n");
625  cnt += buf[cnt+1]+2;
626  break;
627  } else
628  cnt += buf[cnt + 1] + 2;
629  }
630  }
631  }
632 exit:
633  kfree(buf);
634  return ret;
635 }
636 
637 static int r8711_wx_get_name(struct net_device *dev,
638  struct iw_request_info *info,
639  union iwreq_data *wrqu, char *extra)
640 {
641  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
642  u32 ht_ielen = 0;
643  char *p;
644  u8 ht_cap = false;
645  struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
646  struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
647  NDIS_802_11_RATES_EX *prates = NULL;
648 
649  if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) ==
650  true) {
651  /* parsing HT_CAP_IE */
652  p = r8712_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
653  &ht_ielen, pcur_bss->IELength - 12);
654  if (p && ht_ielen > 0)
655  ht_cap = true;
656  prates = &pcur_bss->SupportedRates;
657  if (r8712_is_cckratesonly_included((u8 *)prates) == true) {
658  if (ht_cap == true)
659  snprintf(wrqu->name, IFNAMSIZ,
660  "IEEE 802.11bn");
661  else
662  snprintf(wrqu->name, IFNAMSIZ,
663  "IEEE 802.11b");
664  } else if ((r8712_is_cckrates_included((u8 *)prates)) == true) {
665  if (ht_cap == true)
666  snprintf(wrqu->name, IFNAMSIZ,
667  "IEEE 802.11bgn");
668  else
669  snprintf(wrqu->name, IFNAMSIZ,
670  "IEEE 802.11bg");
671  } else {
672  if (ht_cap == true)
673  snprintf(wrqu->name, IFNAMSIZ,
674  "IEEE 802.11gn");
675  else
676  snprintf(wrqu->name, IFNAMSIZ,
677  "IEEE 802.11g");
678  }
679  } else
680  snprintf(wrqu->name, IFNAMSIZ, "unassociated");
681  return 0;
682 }
683 
684 static const long frequency_list[] = {
685  2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
686  2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
687  5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
688  5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
689  5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
690  5825
691 };
692 
693 static int r8711_wx_set_freq(struct net_device *dev,
694  struct iw_request_info *info,
695  union iwreq_data *wrqu, char *extra)
696 {
697  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
698  struct iw_freq *fwrq = &wrqu->freq;
699  int rc = 0;
700 
701 /* If setting by frequency, convert to a channel */
702  if ((fwrq->e == 1) &&
703  (fwrq->m >= (int) 2.412e8) &&
704  (fwrq->m <= (int) 2.487e8)) {
705  int f = fwrq->m / 100000;
706  int c = 0;
707  while ((c < 14) && (f != frequency_list[c]))
708  c++;
709  fwrq->e = 0;
710  fwrq->m = c + 1;
711  }
712  /* Setting by channel number */
713  if ((fwrq->m > 14) || (fwrq->e > 0))
714  rc = -EOPNOTSUPP;
715  else {
716  int channel = fwrq->m;
717  if ((channel < 1) || (channel > 14))
718  rc = -EINVAL;
719  else {
720  /* Yes ! We can set it !!! */
721  padapter->registrypriv.channel = channel;
722  }
723  }
724  return rc;
725 }
726 
727 static int r8711_wx_get_freq(struct net_device *dev,
728  struct iw_request_info *info,
729  union iwreq_data *wrqu, char *extra)
730 {
731  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
732  struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
733  struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
734 
735  if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
737  pcur_bss->Configuration.DSConfig-1] * 100000;
738  wrqu->freq.e = 1;
739  wrqu->freq.i = pcur_bss->Configuration.DSConfig;
740  } else {
741  return -ENOLINK;
742  }
743  return 0;
744 }
745 
746 static int r8711_wx_set_mode(struct net_device *dev,
747  struct iw_request_info *a,
748  union iwreq_data *wrqu, char *b)
749 {
750  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
751  enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
752 
753  switch (wrqu->mode) {
754  case IW_MODE_AUTO:
755  networkType = Ndis802_11AutoUnknown;
756  break;
757  case IW_MODE_ADHOC:
758  networkType = Ndis802_11IBSS;
759  break;
760  case IW_MODE_MASTER:
761  networkType = Ndis802_11APMode;
762  break;
763  case IW_MODE_INFRA:
764  networkType = Ndis802_11Infrastructure;
765  break;
766  default:
767  return -EINVAL;
768  }
769  if (Ndis802_11APMode == networkType)
770  r8712_setopmode_cmd(padapter, networkType);
771  else
773 
774  r8712_set_802_11_infrastructure_mode(padapter, networkType);
775  return 0;
776 }
777 
778 static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
779  union iwreq_data *wrqu, char *b)
780 {
781  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
782  struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
783 
784  if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
785  wrqu->mode = IW_MODE_INFRA;
786  else if (check_fwstate(pmlmepriv,
788  wrqu->mode = IW_MODE_ADHOC;
789  else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
790  wrqu->mode = IW_MODE_MASTER;
791  else
792  wrqu->mode = IW_MODE_AUTO;
793  return 0;
794 }
795 
796 static int r871x_wx_set_pmkid(struct net_device *dev,
797  struct iw_request_info *a,
798  union iwreq_data *wrqu, char *extra)
799 {
800  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
801  struct security_priv *psecuritypriv = &padapter->securitypriv;
802  struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
803  u8 strZeroMacAddress[ETH_ALEN] = {0x00};
804  u8 strIssueBssid[ETH_ALEN] = {0x00};
805  u8 j, blInserted = false;
806  int intReturn = false;
807 
808 /*
809  There are the BSSID information in the bssid.sa_data array.
810  If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear
811  all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
812  wpa_supplicant wants to add a PMKID/BSSID to driver.
813  If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
814  remove a PMKID/BSSID from driver.
815 */
816  if (pPMK == NULL)
817  return -EINVAL;
818  memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
819  switch (pPMK->cmd) {
820  case IW_PMKSA_ADD:
821  if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
822  return intReturn;
823  else
824  intReturn = true;
825  blInserted = false;
826  /* overwrite PMKID */
827  for (j = 0 ; j < NUM_PMKID_CACHE; j++) {
828  if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
829  strIssueBssid, ETH_ALEN)) {
830  /* BSSID is matched, the same AP => rewrite
831  * with new PMKID. */
832  printk(KERN_INFO "r8712u: r871x_wx_set_pmkid:"
833  " BSSID exists in the PMKList.\n");
834  memcpy(psecuritypriv->PMKIDList[j].PMKID,
835  pPMK->pmkid, IW_PMKID_LEN);
836  psecuritypriv->PMKIDList[j].bUsed = true;
837  psecuritypriv->PMKIDIndex = j + 1;
838  blInserted = true;
839  break;
840  }
841  }
842  if (!blInserted) {
843  /* Find a new entry */
844  printk(KERN_INFO "r8712u: r871x_wx_set_pmkid: Use the"
845  " new entry index = %d for this PMKID.\n",
846  psecuritypriv->PMKIDIndex);
847  memcpy(psecuritypriv->PMKIDList[psecuritypriv->
848  PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
849  memcpy(psecuritypriv->PMKIDList[psecuritypriv->
850  PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
851  psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
852  bUsed = true;
853  psecuritypriv->PMKIDIndex++ ;
854  if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
855  psecuritypriv->PMKIDIndex = 0;
856  }
857  break;
858  case IW_PMKSA_REMOVE:
859  intReturn = true;
860  for (j = 0; j < NUM_PMKID_CACHE; j++) {
861  if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
862  strIssueBssid, ETH_ALEN)) {
863  /* BSSID is matched, the same AP => Remove
864  * this PMKID information and reset it. */
865  memset(psecuritypriv->PMKIDList[j].Bssid,
866  0x00, ETH_ALEN);
867  psecuritypriv->PMKIDList[j].bUsed = false;
868  break;
869  }
870  }
871  break;
872  case IW_PMKSA_FLUSH:
873  memset(psecuritypriv->PMKIDList, 0,
874  sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
875  psecuritypriv->PMKIDIndex = 0;
876  intReturn = true;
877  break;
878  default:
879  printk(KERN_INFO "r8712u: r871x_wx_set_pmkid: "
880  "unknown Command\n");
881  intReturn = false;
882  break;
883  }
884  return intReturn;
885 }
886 
887 static int r8711_wx_get_sens(struct net_device *dev,
888  struct iw_request_info *info,
889  union iwreq_data *wrqu, char *extra)
890 {
891  wrqu->sens.value = 0;
892  wrqu->sens.fixed = 0; /* no auto select */
893  wrqu->sens.disabled = 1;
894  return 0;
895 }
896 
897 static int r8711_wx_get_range(struct net_device *dev,
898  struct iw_request_info *info,
899  union iwreq_data *wrqu, char *extra)
900 {
901  struct iw_range *range = (struct iw_range *)extra;
902  u16 val;
903  int i;
904 
905  wrqu->data.length = sizeof(*range);
906  memset(range, 0, sizeof(*range));
907  /* Let's try to keep this struct in the same order as in
908  * linux/include/wireless.h
909  */
910 
911  /* TODO: See what values we can set, and remove the ones we can't
912  * set, or fill them with some default data.
913  */
914  /* ~5 Mb/s real (802.11b) */
915  range->throughput = 5 * 1000 * 1000;
916  /* TODO: 8711 sensitivity ? */
917  /* signal level threshold range */
918  /* percent values between 0 and 100. */
919  range->max_qual.qual = 100;
920  range->max_qual.level = 100;
921  range->max_qual.noise = 100;
922  range->max_qual.updated = 7; /* Updated all three */
923  range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
924  /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
925  range->avg_qual.level = 20 + -98;
926  range->avg_qual.noise = 0;
927  range->avg_qual.updated = 7; /* Updated all three */
928  range->num_bitrates = RATE_COUNT;
929  for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
930  range->bitrate[i] = rtl8180_rates[i];
931  range->min_frag = MIN_FRAG_THRESHOLD;
932  range->max_frag = MAX_FRAG_THRESHOLD;
933  range->pm_capa = 0;
935  range->we_version_source = 16;
936  range->num_channels = 14;
937  for (i = 0, val = 0; i < 14; i++) {
938  /* Include only legal frequencies for some countries */
939  range->freq[val].i = i + 1;
940  range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
941  range->freq[val].e = 1;
942  val++;
943  if (val == IW_MAX_FREQUENCIES)
944  break;
945  }
946  range->num_frequency = val;
947  range->enc_capa = IW_ENC_CAPA_WPA |
951  return 0;
952 }
953 
954 static int r8711_wx_get_rate(struct net_device *dev,
955  struct iw_request_info *info,
956  union iwreq_data *wrqu, char *extra);
957 
958 static int r871x_wx_set_priv(struct net_device *dev,
959  struct iw_request_info *info,
960  union iwreq_data *awrq,
961  char *extra)
962 {
963  int ret = 0, len = 0;
964  char *ext;
965  struct _adapter *padapter = netdev_priv(dev);
966  struct iw_point *dwrq = (struct iw_point *)awrq;
967 
968  len = dwrq->length;
969  ext = _malloc(len);
970  if (!ext)
971  return -ENOMEM;
972  if (copy_from_user(ext, dwrq->pointer, len)) {
973  kfree(ext);
974  return -EFAULT;
975  }
976 
977  if (0 == strcasecmp(ext, "RSSI")) {
978  /*Return received signal strength indicator in -db for */
979  /* current AP */
980  /*<ssid> Rssi xx */
981  struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
982  struct wlan_network *pcur_network = &pmlmepriv->cur_network;
983  /*static u8 xxxx; */
984  if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
985  sprintf(ext, "%s rssi %d",
986  pcur_network->network.Ssid.Ssid,
987  /*(xxxx=xxxx+10) */
988  ((padapter->recvpriv.fw_rssi)>>1)-95
989  /*pcur_network->network.Rssi */
990  );
991  } else {
992  sprintf(ext, "OK");
993  }
994  } else if (0 == strcasecmp(ext, "LINKSPEED")) {
995  /*Return link speed in MBPS */
996  /*LinkSpeed xx */
997  union iwreq_data wrqd;
998  int ret_inner;
999  int mbps;
1000 
1001  ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
1002  if (0 != ret_inner)
1003  mbps = 0;
1004  else
1005  mbps = wrqd.bitrate.value / 1000000;
1006  sprintf(ext, "LINKSPEED %d", mbps);
1007  } else if (0 == strcasecmp(ext, "MACADDR")) {
1008  /*Return mac address of the station */
1009  /*Macaddr = xx.xx.xx.xx.xx.xx */
1010  sprintf(ext,
1011  "MACADDR = %02x.%02x.%02x.%02x.%02x.%02x",
1012  *(dev->dev_addr), *(dev->dev_addr+1),
1013  *(dev->dev_addr+2), *(dev->dev_addr+3),
1014  *(dev->dev_addr+4), *(dev->dev_addr+5));
1015  } else if (0 == strcasecmp(ext, "SCAN-ACTIVE")) {
1016  /*Set scan type to active */
1017  /*OK if successful */
1018  struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1019  pmlmepriv->passive_mode = 1;
1020  sprintf(ext, "OK");
1021  } else if (0 == strcasecmp(ext, "SCAN-PASSIVE")) {
1022  /*Set scan type to passive */
1023  /*OK if successful */
1024  struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1025  pmlmepriv->passive_mode = 0;
1026  sprintf(ext, "OK");
1027  } else if (0 == strncmp(ext, "DCE-E", 5)) {
1028  /*Set scan type to passive */
1029  /*OK if successful */
1031  , 1 /*u32 enableDrvCtrl */
1032  , 5 /*u32 tryPktCnt */
1033  , 100 /*u32 tryPktInterval */
1034  , 5000 /*u32 firstStageTO */
1035  );
1036  sprintf(ext, "OK");
1037  } else if (0 == strncmp(ext, "DCE-D", 5)) {
1038  /*Set scan type to passive */
1039  /*OK if successfu */
1041  , 0 /*u32 enableDrvCtrl */
1042  , 5 /*u32 tryPktCnt */
1043  , 100 /*u32 tryPktInterval */
1044  , 5000 /*u32 firstStageTO */
1045  );
1046  sprintf(ext, "OK");
1047  } else {
1048  printk(KERN_INFO "r8712u: r871x_wx_set_priv: unknown Command"
1049  " %s.\n", ext);
1050  goto FREE_EXT;
1051  }
1052  if (copy_to_user(dwrq->pointer, ext,
1053  min(dwrq->length, (__u16)(strlen(ext)+1))))
1054  ret = -EFAULT;
1055 
1056 FREE_EXT:
1057  kfree(ext);
1058  return ret;
1059 }
1060 
1061 /* set bssid flow
1062  * s1. set_802_11_infrastructure_mode()
1063  * s2. set_802_11_authentication_mode()
1064  * s3. set_802_11_encryption_mode()
1065  * s4. set_802_11_bssid()
1066  *
1067  * This function intends to handle the Set AP command, which specifies the
1068  * MAC# of a preferred Access Point.
1069  * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
1070  *
1071  * For this operation to succeed, there is no need for the interface to be up.
1072  *
1073  */
1074 static int r8711_wx_set_wap(struct net_device *dev,
1075  struct iw_request_info *info,
1076  union iwreq_data *awrq,
1077  char *extra)
1078 {
1079  int ret = -EINPROGRESS;
1080  struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1081  struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1082  struct __queue *queue = &pmlmepriv->scanned_queue;
1083  struct sockaddr *temp = (struct sockaddr *)awrq;
1084  unsigned long irqL;
1085  struct list_head *phead;
1086  u8 *dst_bssid;
1087  struct wlan_network *pnetwork = NULL;
1088  enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1089 
1090  if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
1091  return -EBUSY;
1092  if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
1093  return ret;
1094  if (temp->sa_family != ARPHRD_ETHER)
1095  return -EINVAL;
1096  authmode = padapter->securitypriv.ndisauthtype;
1097  spin_lock_irqsave(&queue->lock, irqL);
1098  phead = get_list_head(queue);
1099  pmlmepriv->pscanned = get_next(phead);
1100  while (1) {
1101  if (end_of_queue_search(phead, pmlmepriv->pscanned) == true)
1102  break;
1103  pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1104  struct wlan_network, list);
1105  pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1106  dst_bssid = pnetwork->network.MacAddress;
1107  if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
1109  pnetwork->network.InfrastructureMode);
1110  break;
1111  }
1112  }
1113  spin_unlock_irqrestore(&queue->lock, irqL);
1114  if (!ret) {
1115  if (!r8712_set_802_11_authentication_mode(padapter, authmode))
1116  ret = -ENOMEM;
1117  else {
1118  if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
1119  ret = -1;
1120  }
1121  }
1122  return ret;
1123 }
1124 
1125 static int r8711_wx_get_wap(struct net_device *dev,
1126  struct iw_request_info *info,
1127  union iwreq_data *wrqu, char *extra)
1128 {
1129  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1130  struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1131  struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1132 
1133  wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1134  memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1135  if (check_fwstate(pmlmepriv, _FW_LINKED |
1137  memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1138  }
1139  return 0;
1140 }
1141 
1142 static int r871x_wx_set_mlme(struct net_device *dev,
1143  struct iw_request_info *info,
1144  union iwreq_data *wrqu, char *extra)
1145 {
1146  int ret = 0;
1147  u16 reason;
1148  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1149  struct iw_mlme *mlme = (struct iw_mlme *) extra;
1150 
1151  if (mlme == NULL)
1152  return -1;
1153  reason = cpu_to_le16(mlme->reason_code);
1154  switch (mlme->cmd) {
1155  case IW_MLME_DEAUTH:
1156  if (!r8712_set_802_11_disassociate(padapter))
1157  ret = -1;
1158  break;
1159  case IW_MLME_DISASSOC:
1160  if (!r8712_set_802_11_disassociate(padapter))
1161  ret = -1;
1162  break;
1163  default:
1164  return -EOPNOTSUPP;
1165  }
1166  return ret;
1167 }
1168 
1177 static int r8711_wx_set_scan(struct net_device *dev,
1178  struct iw_request_info *a,
1179  union iwreq_data *wrqu, char *extra)
1180 {
1181  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1182  struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1183  u8 status = true;
1184 
1185  if (padapter->bDriverStopped == true) {
1186  printk(KERN_WARNING "r8712u: in r8711_wx_set_scan: "
1187  "bDriverStopped=%d\n", padapter->bDriverStopped);
1188  return -1;
1189  }
1190  if (padapter->bup == false)
1191  return -ENETDOWN;
1192  if (padapter->hw_init_completed == false)
1193  return -1;
1194  if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) ||
1195  (pmlmepriv->sitesurveyctrl.traffic_busy == true))
1196  return 0;
1197  if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1198  struct iw_scan_req *req = (struct iw_scan_req *)extra;
1199  if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1200  struct ndis_802_11_ssid ssid;
1201  unsigned long irqL;
1202  u32 len = (u32) min((u8)req->essid_len,
1204  memset((unsigned char *)&ssid, 0,
1205  sizeof(struct ndis_802_11_ssid));
1206  memcpy(ssid.Ssid, req->essid, len);
1207  ssid.SsidLength = len;
1208  spin_lock_irqsave(&pmlmepriv->lock, irqL);
1209  if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
1210  _FW_UNDER_LINKING)) ||
1211  (pmlmepriv->sitesurveyctrl.traffic_busy == true)) {
1212  if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1213  status = false;
1214  } else
1215  status = r8712_sitesurvey_cmd(padapter, &ssid);
1216  spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1217  }
1218  } else
1219  status = r8712_set_802_11_bssid_list_scan(padapter);
1220  if (status == false)
1221  return -1;
1222  return 0;
1223 }
1224 
1225 static int r8711_wx_get_scan(struct net_device *dev,
1226  struct iw_request_info *a,
1227  union iwreq_data *wrqu, char *extra)
1228 {
1229  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1230  struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1231  struct __queue *queue = &pmlmepriv->scanned_queue;
1232  struct wlan_network *pnetwork = NULL;
1233  unsigned long irqL;
1234  struct list_head *plist, *phead;
1235  char *ev = extra;
1236  char *stop = ev + wrqu->data.length;
1237  u32 ret = 0, cnt = 0;
1238 
1239  if (padapter->bDriverStopped)
1240  return -EINVAL;
1241  while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1242  msleep(30);
1243  cnt++;
1244  if (cnt > 100)
1245  break;
1246  }
1247  spin_lock_irqsave(&queue->lock, irqL);
1248  phead = get_list_head(queue);
1249  plist = get_next(phead);
1250  while (1) {
1251  if (end_of_queue_search(phead, plist) == true)
1252  break;
1253  if ((stop - ev) < SCAN_ITEM_SIZE) {
1254  ret = -E2BIG;
1255  break;
1256  }
1257  pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1258  ev = translate_scan(padapter, a, pnetwork, ev, stop);
1259  plist = get_next(plist);
1260  }
1261  spin_unlock_irqrestore(&queue->lock, irqL);
1262  wrqu->data.length = ev - extra;
1263  wrqu->data.flags = 0;
1264  return ret;
1265 }
1266 
1267 /* set ssid flow
1268  * s1. set_802_11_infrastructure_mode()
1269  * s2. set_802_11_authenticaion_mode()
1270  * s3. set_802_11_encryption_mode()
1271  * s4. set_802_11_ssid()
1272  *
1273  * This function intends to handle the Set ESSID command.
1274  * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
1275  *
1276  * For this operation to succeed, there is no need for the interface to be Up.
1277  *
1278  */
1279 static int r8711_wx_set_essid(struct net_device *dev,
1280  struct iw_request_info *a,
1281  union iwreq_data *wrqu, char *extra)
1282 {
1283  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1284  struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1285  struct __queue *queue = &pmlmepriv->scanned_queue;
1286  struct wlan_network *pnetwork = NULL;
1287  enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1288  struct ndis_802_11_ssid ndis_ssid;
1289  u8 *dst_ssid, *src_ssid;
1290  struct list_head *phead;
1291  u32 len;
1292 
1293  if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1294  return -EBUSY;
1295  if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1296  return 0;
1297  if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
1298  return -E2BIG;
1299  authmode = padapter->securitypriv.ndisauthtype;
1300  if (wrqu->essid.flags && wrqu->essid.length) {
1301  len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
1302  wrqu->essid.length : IW_ESSID_MAX_SIZE;
1303  memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1304  ndis_ssid.SsidLength = len;
1305  memcpy(ndis_ssid.Ssid, extra, len);
1306  src_ssid = ndis_ssid.Ssid;
1307  phead = get_list_head(queue);
1308  pmlmepriv->pscanned = get_next(phead);
1309  while (1) {
1310  if (end_of_queue_search(phead, pmlmepriv->pscanned))
1311  break;
1312  pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1313  struct wlan_network, list);
1314  pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1315  dst_ssid = pnetwork->network.Ssid.Ssid;
1316  if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
1317  && (pnetwork->network.Ssid.SsidLength ==
1318  ndis_ssid.SsidLength)) {
1319  if (check_fwstate(pmlmepriv,
1320  WIFI_ADHOC_STATE)) {
1321  if (pnetwork->network.
1322  InfrastructureMode
1323  !=
1324  padapter->mlmepriv.
1325  cur_network.network.
1326  InfrastructureMode)
1327  continue;
1328  }
1329 
1331  padapter,
1332  pnetwork->network.InfrastructureMode);
1333  break;
1334  }
1335  }
1336  r8712_set_802_11_authentication_mode(padapter, authmode);
1337  r8712_set_802_11_ssid(padapter, &ndis_ssid);
1338  }
1339  return -EINPROGRESS;
1340 }
1341 
1342 static int r8711_wx_get_essid(struct net_device *dev,
1343  struct iw_request_info *a,
1344  union iwreq_data *wrqu, char *extra)
1345 {
1346  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1347  struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1348  struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1349  u32 len, ret = 0;
1350 
1351  if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1352  len = pcur_bss->Ssid.SsidLength;
1353  wrqu->essid.length = len;
1354  memcpy(extra, pcur_bss->Ssid.Ssid, len);
1355  wrqu->essid.flags = 1;
1356  } else {
1357  ret = -ENOLINK;
1358  }
1359  return ret;
1360 }
1361 
1362 static int r8711_wx_set_rate(struct net_device *dev,
1363  struct iw_request_info *a,
1364  union iwreq_data *wrqu, char *extra)
1365 {
1366  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1367  u32 target_rate = wrqu->bitrate.value;
1368  u32 fixed = wrqu->bitrate.fixed;
1369  u32 ratevalue = 0;
1370  u8 datarates[NumRates];
1371  u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1372  int i, ret = 0;
1373 
1374  if (target_rate == -1) {
1375  ratevalue = 11;
1376  goto set_rate;
1377  }
1378  target_rate = target_rate / 100000;
1379  switch (target_rate) {
1380  case 10:
1381  ratevalue = 0;
1382  break;
1383  case 20:
1384  ratevalue = 1;
1385  break;
1386  case 55:
1387  ratevalue = 2;
1388  break;
1389  case 60:
1390  ratevalue = 3;
1391  break;
1392  case 90:
1393  ratevalue = 4;
1394  break;
1395  case 110:
1396  ratevalue = 5;
1397  break;
1398  case 120:
1399  ratevalue = 6;
1400  break;
1401  case 180:
1402  ratevalue = 7;
1403  break;
1404  case 240:
1405  ratevalue = 8;
1406  break;
1407  case 360:
1408  ratevalue = 9;
1409  break;
1410  case 480:
1411  ratevalue = 10;
1412  break;
1413  case 540:
1414  ratevalue = 11;
1415  break;
1416  default:
1417  ratevalue = 11;
1418  break;
1419  }
1420 set_rate:
1421  for (i = 0; i < NumRates; i++) {
1422  if (ratevalue == mpdatarate[i]) {
1423  datarates[i] = mpdatarate[i];
1424  if (fixed == 0)
1425  break;
1426  } else
1427  datarates[i] = 0xff;
1428  }
1429  if (r8712_setdatarate_cmd(padapter, datarates) != _SUCCESS)
1430  ret = -ENOMEM;
1431  return ret;
1432 }
1433 
1434 static int r8711_wx_get_rate(struct net_device *dev,
1435  struct iw_request_info *info,
1436  union iwreq_data *wrqu, char *extra)
1437 {
1438  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1439  struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1440  struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1441  struct ieee80211_ht_cap *pht_capie;
1442  unsigned char rf_type = padapter->registrypriv.rf_config;
1443  int i;
1444  u8 *p;
1445  u16 rate, max_rate = 0, ht_cap = false;
1446  u32 ht_ielen = 0;
1447  u8 bw_40MHz = 0, short_GI = 0;
1448  u16 mcs_rate = 0;
1449 
1450  i = 0;
1451  if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
1452  p = r8712_get_ie(&pcur_bss->IEs[12],
1453  _HT_CAPABILITY_IE_, &ht_ielen,
1454  pcur_bss->IELength - 12);
1455  if (p && ht_ielen > 0) {
1456  ht_cap = true;
1457  pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1458  memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
1459  bw_40MHz = (pht_capie->cap_info &
1460  IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
1461  short_GI = (pht_capie->cap_info &
1463  IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
1464  }
1465  while ((pcur_bss->SupportedRates[i] != 0) &&
1466  (pcur_bss->SupportedRates[i] != 0xFF)) {
1467  rate = pcur_bss->SupportedRates[i] & 0x7F;
1468  if (rate > max_rate)
1469  max_rate = rate;
1470  wrqu->bitrate.fixed = 0; /* no auto select */
1471  wrqu->bitrate.value = rate*500000;
1472  i++;
1473  }
1474  if (ht_cap == true) {
1475  if (mcs_rate & 0x8000 /* MCS15 */
1476  &&
1477  RTL8712_RF_2T2R == rf_type)
1478  max_rate = (bw_40MHz) ? ((short_GI) ? 300 :
1479  270) : ((short_GI) ? 144 : 130);
1480  else if (mcs_rate & 0x0080) /* MCS7 */
1481  max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1482  135) : ((short_GI) ? 72 : 65);
1483  else /* default MCS7 */
1484  max_rate = (bw_40MHz) ? ((short_GI) ? 150 :
1485  135) : ((short_GI) ? 72 : 65);
1486  max_rate *= 2; /* Mbps/2 */
1487  wrqu->bitrate.value = max_rate * 500000;
1488  } else {
1489  wrqu->bitrate.value = max_rate * 500000;
1490  }
1491  } else
1492  return -ENOLINK;
1493  return 0;
1494 }
1495 
1496 static int r8711_wx_get_rts(struct net_device *dev,
1497  struct iw_request_info *info,
1498  union iwreq_data *wrqu, char *extra)
1499 {
1500  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1501 
1502  wrqu->rts.value = padapter->registrypriv.rts_thresh;
1503  wrqu->rts.fixed = 0; /* no auto select */
1504  return 0;
1505 }
1506 
1507 static int r8711_wx_set_frag(struct net_device *dev,
1508  struct iw_request_info *info,
1509  union iwreq_data *wrqu, char *extra)
1510 {
1511  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1512 
1513  if (wrqu->frag.disabled)
1514  padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1515  else {
1516  if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1517  wrqu->frag.value > MAX_FRAG_THRESHOLD)
1518  return -EINVAL;
1519  padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1520  }
1521  return 0;
1522 }
1523 
1524 static int r8711_wx_get_frag(struct net_device *dev,
1525  struct iw_request_info *info,
1526  union iwreq_data *wrqu, char *extra)
1527 {
1528  struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1529 
1530  wrqu->frag.value = padapter->xmitpriv.frag_len;
1531  wrqu->frag.fixed = 0; /* no auto select */
1532  return 0;
1533 }
1534 
1535 static int r8711_wx_get_retry(struct net_device *dev,
1536  struct iw_request_info *info,
1537  union iwreq_data *wrqu, char *extra)
1538 {
1539  wrqu->retry.value = 7;
1540  wrqu->retry.fixed = 0; /* no auto select */
1541  wrqu->retry.disabled = 1;
1542  return 0;
1543 }
1544 
1545 static int r8711_wx_set_enc(struct net_device *dev,
1546  struct iw_request_info *info,
1547  union iwreq_data *wrqu, char *keybuf)
1548 {
1549  u32 key;
1550  u32 keyindex_provided;
1551  struct NDIS_802_11_WEP wep;
1552  enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1553  struct iw_point *erq = &(wrqu->encoding);
1554  struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1555 
1556  key = erq->flags & IW_ENCODE_INDEX;
1557  memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
1558  if (erq->flags & IW_ENCODE_DISABLED) {
1559  printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
1560  "EncryptionDisabled\n");
1561  padapter->securitypriv.ndisencryptstatus =
1563  padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1564  padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1565  padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1566  authmode = Ndis802_11AuthModeOpen;
1567  padapter->securitypriv.ndisauthtype = authmode;
1568  return 0;
1569  }
1570  if (key) {
1571  if (key > WEP_KEYS)
1572  return -EINVAL;
1573  key--;
1574  keyindex_provided = 1;
1575  } else {
1576  keyindex_provided = 0;
1577  key = padapter->securitypriv.PrivacyKeyIndex;
1578  }
1579  /* set authentication mode */
1580  if (erq->flags & IW_ENCODE_OPEN) {
1581  printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
1582  "IW_ENCODE_OPEN\n");
1583  padapter->securitypriv.ndisencryptstatus =
1585  padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1586  padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1587  padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1588  authmode = Ndis802_11AuthModeOpen;
1589  padapter->securitypriv.ndisauthtype = authmode;
1590  } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1591  printk(KERN_INFO "r8712u: r8711_wx_set_enc: "
1592  "IW_ENCODE_RESTRICTED\n");
1593  padapter->securitypriv.ndisencryptstatus =
1595  padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
1596  padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
1597  padapter->securitypriv.XGrpPrivacy = _WEP40_;
1598  authmode = Ndis802_11AuthModeShared;
1599  padapter->securitypriv.ndisauthtype = authmode;
1600  } else {
1601  padapter->securitypriv.ndisencryptstatus =
1603  padapter->securitypriv.AuthAlgrthm = 0; /* open system */
1604  padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
1605  padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
1606  authmode = Ndis802_11AuthModeOpen;
1607  padapter->securitypriv.ndisauthtype = authmode;
1608  }
1609  wep.KeyIndex = key;
1610  if (erq->length > 0) {
1611  wep.KeyLength = erq->length <= 5 ? 5 : 13;
1612  wep.Length = wep.KeyLength +
1613  FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
1614  } else {
1615  wep.KeyLength = 0 ;
1616  if (keyindex_provided == 1) { /* set key_id only, no given
1617  * KeyMaterial(erq->length==0).*/
1618  padapter->securitypriv.PrivacyKeyIndex = key;
1619  switch (padapter->securitypriv.DefKeylen[key]) {
1620  case 5:
1621  padapter->securitypriv.PrivacyAlgrthm =
1622  _WEP40_;
1623  break;
1624  case 13:
1625  padapter->securitypriv.PrivacyAlgrthm =
1626  _WEP104_;
1627  break;
1628  default:
1629  padapter->securitypriv.PrivacyAlgrthm =
1630  _NO_PRIVACY_;
1631  break;
1632  }
1633  return 0;
1634  }
1635  }
1636  wep.KeyIndex |= 0x80000000; /* transmit key */
1637  memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1638  if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL)
1639  return -EOPNOTSUPP;
1640  return 0;
1641 }
1642 
1643 static int r8711_wx_get_enc(struct net_device *dev,
1644  struct iw_request_info *info,
1645  union iwreq_data *wrqu, char *keybuf)
1646 {
1647  uint key, ret = 0;
1648  struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1649  struct iw_point *erq = &(wrqu->encoding);
1650  struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1651 
1652  if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
1653  if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1654  erq->length = 0;
1655  erq->flags |= IW_ENCODE_DISABLED;
1656  return 0;
1657  }
1658  }
1659  key = erq->flags & IW_ENCODE_INDEX;
1660  if (key) {
1661  if (key > WEP_KEYS)
1662  return -EINVAL;
1663  key--;
1664  } else {
1665  key = padapter->securitypriv.PrivacyKeyIndex;
1666  }
1667  erq->flags = key + 1;
1668  switch (padapter->securitypriv.ndisencryptstatus) {
1671  erq->length = 0;
1672  erq->flags |= IW_ENCODE_DISABLED;
1673  break;
1675  erq->length = padapter->securitypriv.DefKeylen[key];
1676  if (erq->length) {
1677  memcpy(keybuf, padapter->securitypriv.DefKey[
1678  key].skey, padapter->securitypriv.
1679  DefKeylen[key]);
1680  erq->flags |= IW_ENCODE_ENABLED;
1681  if (padapter->securitypriv.ndisauthtype ==
1683  erq->flags |= IW_ENCODE_OPEN;
1684  else if (padapter->securitypriv.ndisauthtype ==
1686  erq->flags |= IW_ENCODE_RESTRICTED;
1687  } else {
1688  erq->length = 0;
1689  erq->flags |= IW_ENCODE_DISABLED;
1690  }
1691  break;
1694  erq->length = 16;
1696  IW_ENCODE_NOKEY);
1697  break;
1698  default:
1699  erq->length = 0;
1700  erq->flags |= IW_ENCODE_DISABLED;
1701  break;
1702  }
1703  return ret;
1704 }
1705 
1706 static int r8711_wx_get_power(struct net_device *dev,
1707  struct iw_request_info *info,
1708  union iwreq_data *wrqu, char *extra)
1709 {
1710  wrqu->power.value = 0;
1711  wrqu->power.fixed = 0; /* no auto select */
1712  wrqu->power.disabled = 1;
1713  return 0;
1714 }
1715 
1716 static int r871x_wx_set_gen_ie(struct net_device *dev,
1717  struct iw_request_info *info,
1718  union iwreq_data *wrqu, char *extra)
1719 {
1720  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1721 
1722  return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
1723 }
1724 
1725 static int r871x_wx_set_auth(struct net_device *dev,
1726  struct iw_request_info *info,
1727  union iwreq_data *wrqu, char *extra)
1728 {
1729  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1730  struct iw_param *param = (struct iw_param *)&(wrqu->param);
1731  int paramid;
1732  int paramval;
1733  int ret = 0;
1734 
1735  paramid = param->flags & IW_AUTH_INDEX;
1736  paramval = param->value;
1737  switch (paramid) {
1738  case IW_AUTH_WPA_VERSION:
1739  break;
1741  break;
1742  case IW_AUTH_CIPHER_GROUP:
1743  break;
1744  case IW_AUTH_KEY_MGMT:
1745  /*
1746  * ??? does not use these parameters
1747  */
1748  break;
1750  if (paramval) {
1751  /* wpa_supplicant is enabling tkip countermeasure. */
1752  padapter->securitypriv.btkip_countermeasure = true;
1753  } else {
1754  /* wpa_supplicant is disabling tkip countermeasure. */
1755  padapter->securitypriv.btkip_countermeasure = false;
1756  }
1757  break;
1759  /* HACK:
1760  *
1761  * wpa_supplicant calls set_wpa_enabled when the driver
1762  * is loaded and unloaded, regardless of if WPA is being
1763  * used. No other calls are made which can be used to
1764  * determine if encryption will be used or not prior to
1765  * association being expected. If encryption is not being
1766  * used, drop_unencrypted is set to false, else true -- we
1767  * can use this to determine if the CAP_PRIVACY_ON bit should
1768  * be set.
1769  */
1770  if (padapter->securitypriv.ndisencryptstatus ==
1772  /* it means init value, or using wep,
1773  * ndisencryptstatus =
1774  * Ndis802_11Encryption1Enabled,
1775  * then it needn't reset it;
1776  */
1777  break;
1778  }
1779 
1780  if (paramval) {
1781  padapter->securitypriv.ndisencryptstatus =
1783  padapter->securitypriv.PrivacyAlgrthm =
1784  _NO_PRIVACY_;
1785  padapter->securitypriv.XGrpPrivacy =
1786  _NO_PRIVACY_;
1787  padapter->securitypriv.AuthAlgrthm = 0;
1788  padapter->securitypriv.ndisauthtype =
1790  }
1791  break;
1793  ret = wpa_set_auth_algs(dev, (u32)paramval);
1794  break;
1795  case IW_AUTH_WPA_ENABLED:
1796  break;
1798  break;
1800  break;
1801  default:
1802  return -EOPNOTSUPP;
1803  }
1804 
1805  return ret;
1806 }
1807 
1808 static int r871x_wx_set_enc_ext(struct net_device *dev,
1809  struct iw_request_info *info,
1810  union iwreq_data *wrqu, char *extra)
1811 {
1812  struct iw_point *pencoding = &wrqu->encoding;
1813  struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1814  struct ieee_param *param = NULL;
1815  char *alg_name;
1816  u32 param_len;
1817  int ret = 0;
1818 
1819  param_len = sizeof(struct ieee_param) + pext->key_len;
1820  param = (struct ieee_param *)_malloc(param_len);
1821  if (param == NULL)
1822  return -ENOMEM;
1823  memset(param, 0, param_len);
1824  param->cmd = IEEE_CMD_SET_ENCRYPTION;
1825  memset(param->sta_addr, 0xff, ETH_ALEN);
1826  switch (pext->alg) {
1827  case IW_ENCODE_ALG_NONE:
1828  alg_name = "none";
1829  break;
1830  case IW_ENCODE_ALG_WEP:
1831  alg_name = "WEP";
1832  break;
1833  case IW_ENCODE_ALG_TKIP:
1834  alg_name = "TKIP";
1835  break;
1836  case IW_ENCODE_ALG_CCMP:
1837  alg_name = "CCMP";
1838  break;
1839  default:
1840  return -EINVAL;
1841  }
1842  strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1843  if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1844  param->u.crypt.set_tx = 0;
1845  if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1846  param->u.crypt.set_tx = 1;
1847  param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1849  memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1850  if (pext->key_len) {
1851  param->u.crypt.key_len = pext->key_len;
1852  memcpy(param + 1, pext + 1, pext->key_len);
1853  }
1854  ret = wpa_set_encryption(dev, param, param_len);
1855  kfree(param);
1856  return ret;
1857 }
1858 
1859 static int r871x_wx_get_nick(struct net_device *dev,
1860  struct iw_request_info *info,
1861  union iwreq_data *wrqu, char *extra)
1862 {
1863  if (extra) {
1864  wrqu->data.length = 8;
1865  wrqu->data.flags = 1;
1866  memcpy(extra, "rtl_wifi", 8);
1867  }
1868  return 0;
1869 }
1870 
1871 static int r8711_wx_read32(struct net_device *dev,
1872  struct iw_request_info *info,
1873  union iwreq_data *wrqu, char *keybuf)
1874 {
1875  struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1876  u32 addr;
1877  u32 data32;
1878 
1879  get_user(addr, (u32 __user *)wrqu->data.pointer);
1880  data32 = r8712_read32(padapter, addr);
1881  put_user(data32, (u32 __user *)wrqu->data.pointer);
1882  wrqu->data.length = (data32 & 0xffff0000) >> 16;
1883  wrqu->data.flags = data32 & 0xffff;
1884  get_user(addr, (u32 __user *)wrqu->data.pointer);
1885  return 0;
1886 }
1887 
1888 static int r8711_wx_write32(struct net_device *dev,
1889  struct iw_request_info *info,
1890  union iwreq_data *wrqu, char *keybuf)
1891 {
1892  struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
1893  u32 addr;
1894  u32 data32;
1895 
1896  get_user(addr, (u32 __user *)wrqu->data.pointer);
1897  data32 = ((u32)wrqu->data.length<<16) | (u32)wrqu->data.flags ;
1898  r8712_write32(padapter, addr, data32);
1899  return 0;
1900 }
1901 
1902 static int dummy(struct net_device *dev,
1903  struct iw_request_info *a,
1904  union iwreq_data *wrqu, char *b)
1905 {
1906  return -ENOSYS;
1907 }
1908 
1909 static int r8711_drvext_hdl(struct net_device *dev,
1910  struct iw_request_info *info,
1911  union iwreq_data *wrqu, char *extra)
1912 {
1913  return 0;
1914 }
1915 
1916 static int r871x_mp_ioctl_hdl(struct net_device *dev,
1917  struct iw_request_info *info,
1918  union iwreq_data *wrqu, char *extra)
1919 {
1920  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
1921  struct iw_point *p = &wrqu->data;
1922  struct oid_par_priv oid_par;
1923  struct mp_ioctl_handler *phandler;
1924  struct mp_ioctl_param *poidparam;
1925  unsigned long BytesRead, BytesWritten, BytesNeeded;
1926  u8 *pparmbuf = NULL, bset;
1927  u16 len;
1928  uint status;
1929  int ret = 0;
1930 
1931  if ((!p->length) || (!p->pointer)) {
1932  ret = -EINVAL;
1933  goto _r871x_mp_ioctl_hdl_exit;
1934  }
1935  bset = (u8)(p->flags & 0xFFFF);
1936  len = p->length;
1937  pparmbuf = NULL;
1938  pparmbuf = (u8 *)_malloc(len);
1939  if (pparmbuf == NULL) {
1940  ret = -ENOMEM;
1941  goto _r871x_mp_ioctl_hdl_exit;
1942  }
1943  if (copy_from_user(pparmbuf, p->pointer, len)) {
1944  ret = -EFAULT;
1945  goto _r871x_mp_ioctl_hdl_exit;
1946  }
1947  poidparam = (struct mp_ioctl_param *)pparmbuf;
1948  if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
1949  ret = -EINVAL;
1950  goto _r871x_mp_ioctl_hdl_exit;
1951  }
1952  phandler = mp_ioctl_hdl + poidparam->subcode;
1953  if ((phandler->paramsize != 0) &&
1954  (poidparam->len < phandler->paramsize)) {
1955  ret = -EINVAL;
1956  goto _r871x_mp_ioctl_hdl_exit;
1957  }
1958  if (phandler->oid == 0 && phandler->handler)
1959  status = phandler->handler(&oid_par);
1960  else if (phandler->handler) {
1961  oid_par.adapter_context = padapter;
1962  oid_par.oid = phandler->oid;
1963  oid_par.information_buf = poidparam->data;
1964  oid_par.information_buf_len = poidparam->len;
1965  oid_par.dbg = 0;
1966  BytesWritten = 0;
1967  BytesNeeded = 0;
1968  if (bset) {
1969  oid_par.bytes_rw = &BytesRead;
1970  oid_par.bytes_needed = &BytesNeeded;
1971  oid_par.type_of_oid = SET_OID;
1972  } else {
1973  oid_par.bytes_rw = &BytesWritten;
1974  oid_par.bytes_needed = &BytesNeeded;
1975  oid_par.type_of_oid = QUERY_OID;
1976  }
1977  status = phandler->handler(&oid_par);
1978  /* todo:check status, BytesNeeded, etc. */
1979  } else {
1980  printk(KERN_INFO "r8712u: r871x_mp_ioctl_hdl(): err!,"
1981  " subcode=%d, oid=%d, handler=%p\n",
1982  poidparam->subcode, phandler->oid, phandler->handler);
1983  ret = -EFAULT;
1984  goto _r871x_mp_ioctl_hdl_exit;
1985  }
1986  if (bset == 0x00) { /* query info */
1987  if (copy_to_user(p->pointer, pparmbuf, len))
1988  ret = -EFAULT;
1989  }
1990  if (status) {
1991  ret = -EFAULT;
1992  goto _r871x_mp_ioctl_hdl_exit;
1993  }
1994 _r871x_mp_ioctl_hdl_exit:
1995  kfree(pparmbuf);
1996  return ret;
1997 }
1998 
1999 static int r871x_get_ap_info(struct net_device *dev,
2000  struct iw_request_info *info,
2001  union iwreq_data *wrqu, char *extra)
2002 {
2003  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2004  struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2005  struct __queue *queue = &pmlmepriv->scanned_queue;
2006  struct iw_point *pdata = &wrqu->data;
2007  struct wlan_network *pnetwork = NULL;
2008  u32 cnt = 0, wpa_ielen;
2009  unsigned long irqL;
2010  struct list_head *plist, *phead;
2011  unsigned char *pbuf;
2012  u8 bssid[ETH_ALEN];
2013  char data[32];
2014 
2015  if (padapter->bDriverStopped || (pdata == NULL))
2016  return -EINVAL;
2017  while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
2018  msleep(30);
2019  cnt++;
2020  if (cnt > 100)
2021  break;
2022  }
2023  pdata->flags = 0;
2024  if (pdata->length >= 32) {
2025  if (copy_from_user(data, pdata->pointer, 32))
2026  return -EINVAL;
2027  } else
2028  return -EINVAL;
2029  spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL);
2030  phead = get_list_head(queue);
2031  plist = get_next(phead);
2032  while (1) {
2033  if (end_of_queue_search(phead, plist) == true)
2034  break;
2035  pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
2036  if (hwaddr_aton_i(data, bssid)) {
2037  printk(KERN_INFO "r8712u: Invalid BSSID '%s'.\n",
2038  (u8 *)data);
2039  spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock),
2040  irqL);
2041  return -EINVAL;
2042  }
2043  printk(KERN_INFO "r8712u: BSSID:%pM\n", bssid);
2044  if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
2045  /* BSSID match, then check if supporting wpa/wpa2 */
2046  pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
2047  &wpa_ielen, pnetwork->network.IELength-12);
2048  if (pbuf && (wpa_ielen > 0)) {
2049  pdata->flags = 1;
2050  break;
2051  }
2052  pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
2053  &wpa_ielen, pnetwork->network.IELength-12);
2054  if (pbuf && (wpa_ielen > 0)) {
2055  pdata->flags = 2;
2056  break;
2057  }
2058  }
2059  plist = get_next(plist);
2060  }
2061  spin_unlock_irqrestore(&(pmlmepriv->scanned_queue.lock), irqL);
2062  if (pdata->length >= 34) {
2063  if (copy_to_user((u8 __user *)pdata->pointer + 32,
2064  (u8 *)&pdata->flags, 1))
2065  return -EINVAL;
2066  }
2067  return 0;
2068 }
2069 
2070 static int r871x_set_pid(struct net_device *dev,
2071  struct iw_request_info *info,
2072  union iwreq_data *wrqu, char *extra)
2073 {
2074  struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2075  struct iw_point *pdata = &wrqu->data;
2076 
2077  if ((padapter->bDriverStopped) || (pdata == NULL))
2078  return -EINVAL;
2079  if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int)))
2080  return -EINVAL;
2081  return 0;
2082 }
2083 
2084 static int r871x_set_chplan(struct net_device *dev,
2085  struct iw_request_info *info,
2086  union iwreq_data *wrqu, char *extra)
2087 {
2088  int ret = 0;
2089  struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2090  struct iw_point *pdata = &wrqu->data;
2091  int ch_plan = -1;
2092 
2093  if ((padapter->bDriverStopped) || (pdata == NULL)) {
2094  ret = -EINVAL;
2095  goto exit;
2096  }
2097  ch_plan = (int)*extra;
2098  r8712_set_chplan_cmd(padapter, ch_plan);
2099 
2100 exit:
2101 
2102  return ret;
2103 }
2104 
2105 static int r871x_wps_start(struct net_device *dev,
2106  struct iw_request_info *info,
2107  union iwreq_data *wrqu, char *extra)
2108 {
2109  struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
2110  struct iw_point *pdata = &wrqu->data;
2111  u32 u32wps_start = 0;
2112 
2113  if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
2114  return -EFAULT;
2115  if ((padapter->bDriverStopped) || (pdata == NULL))
2116  return -EINVAL;
2117  if (u32wps_start == 0)
2118  u32wps_start = *extra;
2119  if (u32wps_start == 1) /* WPS Start */
2120  padapter->ledpriv.LedControlHandler(padapter,
2122  else if (u32wps_start == 2) /* WPS Stop because of wps success */
2123  padapter->ledpriv.LedControlHandler(padapter,
2125  else if (u32wps_start == 3) /* WPS Stop because of wps fail */
2126  padapter->ledpriv.LedControlHandler(padapter,
2128  return 0;
2129 }
2130 
2131 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
2132 {
2133  struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2134 
2135  switch (name) {
2137  padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
2138  switch ((value)&0xff) {
2139  case 1: /* WPA */
2140  padapter->securitypriv.ndisauthtype =
2141  Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
2142  padapter->securitypriv.ndisencryptstatus =
2144  break;
2145  case 2: /* WPA2 */
2146  padapter->securitypriv.ndisauthtype =
2147  Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
2148  padapter->securitypriv.ndisencryptstatus =
2150  break;
2151  }
2152  break;
2154  break;
2156  /* HACK:
2157  *
2158  * wpa_supplicant calls set_wpa_enabled when the driver
2159  * is loaded and unloaded, regardless of if WPA is being
2160  * used. No other calls are made which can be used to
2161  * determine if encryption will be used or not prior to
2162  * association being expected. If encryption is not being
2163  * used, drop_unencrypted is set to false, else true -- we
2164  * can use this to determine if the CAP_PRIVACY_ON bit should
2165  * be set.
2166  */
2167  break;
2169  break;
2170  case IEEE_PARAM_AUTH_ALGS:
2171  return wpa_set_auth_algs(dev, value);
2172  break;
2174  break;
2176  /* added for WPA2 mixed mode */
2177  break;
2178  default:
2179  return -EOPNOTSUPP;
2180  }
2181  return 0;
2182 }
2183 
2184 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
2185 {
2186  struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2187 
2188  switch (command) {
2189  case IEEE_MLME_STA_DEAUTH:
2190  if (!r8712_set_802_11_disassociate(padapter))
2191  return -1;
2192  break;
2194  if (!r8712_set_802_11_disassociate(padapter))
2195  return -1;
2196  break;
2197  default:
2198  return -EOPNOTSUPP;
2199  }
2200  return 0;
2201 }
2202 
2203 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
2204 {
2205  struct ieee_param *param;
2206  int ret = 0;
2207  struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2208 
2209  if (p->length < sizeof(struct ieee_param) || !p->pointer)
2210  return -EINVAL;
2211  param = (struct ieee_param *)_malloc(p->length);
2212  if (param == NULL)
2213  return -ENOMEM;
2214  if (copy_from_user(param, p->pointer, p->length)) {
2215  kfree((u8 *)param);
2216  return -EFAULT;
2217  }
2218  switch (param->cmd) {
2220  ret = wpa_set_param(dev, param->u.wpa_param.name,
2221  param->u.wpa_param.value);
2222  break;
2223  case IEEE_CMD_SET_WPA_IE:
2224  ret = r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
2225  (u16)param->u.wpa_ie.len);
2226  break;
2228  ret = wpa_set_encryption(dev, param, p->length);
2229  break;
2230  case IEEE_CMD_MLME:
2231  ret = wpa_mlme(dev, param->u.mlme.command,
2232  param->u.mlme.reason_code);
2233  break;
2234  default:
2235  ret = -EOPNOTSUPP;
2236  break;
2237  }
2238  if (ret == 0 && copy_to_user(p->pointer, param, p->length))
2239  ret = -EFAULT;
2240  kfree((u8 *)param);
2241  return ret;
2242 }
2243 
2244 /* based on "driver_ipw" and for hostapd */
2245 int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2246 {
2247  struct iwreq *wrq = (struct iwreq *)rq;
2248 
2249  switch (cmd) {
2251  return wpa_supplicant_ioctl(dev, &wrq->u.data);
2252  default:
2253  return -EOPNOTSUPP;
2254  }
2255  return 0;
2256 }
2257 
2258 static iw_handler r8711_handlers[] = {
2259  NULL, /* SIOCSIWCOMMIT */
2260  r8711_wx_get_name, /* SIOCGIWNAME */
2261  dummy, /* SIOCSIWNWID */
2262  dummy, /* SIOCGIWNWID */
2263  r8711_wx_set_freq, /* SIOCSIWFREQ */
2264  r8711_wx_get_freq, /* SIOCGIWFREQ */
2265  r8711_wx_set_mode, /* SIOCSIWMODE */
2266  r8711_wx_get_mode, /* SIOCGIWMODE */
2267  dummy, /* SIOCSIWSENS */
2268  r8711_wx_get_sens, /* SIOCGIWSENS */
2269  NULL, /* SIOCSIWRANGE */
2270  r8711_wx_get_range, /* SIOCGIWRANGE */
2271  r871x_wx_set_priv, /* SIOCSIWPRIV */
2272  NULL, /* SIOCGIWPRIV */
2273  NULL, /* SIOCSIWSTATS */
2274  NULL, /* SIOCGIWSTATS */
2275  dummy, /* SIOCSIWSPY */
2276  dummy, /* SIOCGIWSPY */
2277  NULL, /* SIOCGIWTHRSPY */
2278  NULL, /* SIOCWIWTHRSPY */
2279  r8711_wx_set_wap, /* SIOCSIWAP */
2280  r8711_wx_get_wap, /* SIOCGIWAP */
2281  r871x_wx_set_mlme, /* request MLME operation;
2282  * uses struct iw_mlme */
2283  dummy, /* SIOCGIWAPLIST -- deprecated */
2284  r8711_wx_set_scan, /* SIOCSIWSCAN */
2285  r8711_wx_get_scan, /* SIOCGIWSCAN */
2286  r8711_wx_set_essid, /* SIOCSIWESSID */
2287  r8711_wx_get_essid, /* SIOCGIWESSID */
2288  dummy, /* SIOCSIWNICKN */
2289  r871x_wx_get_nick, /* SIOCGIWNICKN */
2290  NULL, /* -- hole -- */
2291  NULL, /* -- hole -- */
2292  r8711_wx_set_rate, /* SIOCSIWRATE */
2293  r8711_wx_get_rate, /* SIOCGIWRATE */
2294  dummy, /* SIOCSIWRTS */
2295  r8711_wx_get_rts, /* SIOCGIWRTS */
2296  r8711_wx_set_frag, /* SIOCSIWFRAG */
2297  r8711_wx_get_frag, /* SIOCGIWFRAG */
2298  dummy, /* SIOCSIWTXPOW */
2299  dummy, /* SIOCGIWTXPOW */
2300  dummy, /* SIOCSIWRETRY */
2301  r8711_wx_get_retry, /* SIOCGIWRETRY */
2302  r8711_wx_set_enc, /* SIOCSIWENCODE */
2303  r8711_wx_get_enc, /* SIOCGIWENCODE */
2304  dummy, /* SIOCSIWPOWER */
2305  r8711_wx_get_power, /* SIOCGIWPOWER */
2306  NULL, /*---hole---*/
2307  NULL, /*---hole---*/
2308  r871x_wx_set_gen_ie, /* SIOCSIWGENIE */
2309  NULL, /* SIOCGIWGENIE */
2310  r871x_wx_set_auth, /* SIOCSIWAUTH */
2311  NULL, /* SIOCGIWAUTH */
2312  r871x_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
2313  NULL, /* SIOCGIWENCODEEXT */
2314  r871x_wx_set_pmkid, /* SIOCSIWPMKSA */
2315  NULL, /*---hole---*/
2316 };
2317 
2318 static const struct iw_priv_args r8711_private_args[] = {
2319  {
2320  SIOCIWFIRSTPRIV + 0x0,
2321  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
2322  },
2323  {
2324  SIOCIWFIRSTPRIV + 0x1,
2325  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
2326  },
2327  {
2328  SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
2329  },
2330  {
2331  SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
2332  },
2333  {
2334  SIOCIWFIRSTPRIV + 0x4,
2335  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
2336  },
2337  {
2338  SIOCIWFIRSTPRIV + 0x5,
2339  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
2340  },
2341  {
2342  SIOCIWFIRSTPRIV + 0x6,
2343  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
2344  },
2345  {
2346  SIOCIWFIRSTPRIV + 0x7,
2347  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
2348  }
2349 };
2350 
2351 static iw_handler r8711_private_handler[] = {
2352  r8711_wx_read32,
2353  r8711_wx_write32,
2354  r8711_drvext_hdl,
2355  r871x_mp_ioctl_hdl,
2356  r871x_get_ap_info, /*for MM DTV platform*/
2357  r871x_set_pid,
2358  r871x_wps_start,
2359  r871x_set_chplan
2360 };
2361 
2362 static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
2363 {
2364  struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
2365  struct iw_statistics *piwstats = &padapter->iwstats;
2366  int tmp_level = 0;
2367  int tmp_qual = 0;
2368  int tmp_noise = 0;
2369 
2370  if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
2371  piwstats->qual.qual = 0;
2372  piwstats->qual.level = 0;
2373  piwstats->qual.noise = 0;
2374  } else {
2375  /* show percentage, we need transfer dbm to orignal value. */
2376  tmp_level = padapter->recvpriv.fw_rssi;
2377  tmp_qual = padapter->recvpriv.signal;
2378  tmp_noise = padapter->recvpriv.noise;
2379  piwstats->qual.level = tmp_level;
2380  piwstats->qual.qual = tmp_qual;
2381  piwstats->qual.noise = tmp_noise;
2382  }
2383  piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
2384  return &padapter->iwstats;
2385 }
2386 
2388  .standard = r8711_handlers,
2389  .num_standard = ARRAY_SIZE(r8711_handlers),
2390  .private = r8711_private_handler,
2391  .private_args = (struct iw_priv_args *)r8711_private_args,
2392  .num_private = ARRAY_SIZE(r8711_private_handler),
2393  .num_private_args = sizeof(r8711_private_args) /
2394  sizeof(struct iw_priv_args),
2395  .get_wireless_stats = r871x_get_wireless_stats
2396 };