PageRenderTime 63ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/drivers/staging/rtl8712/rtl871x_ioctl_linux.c

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