1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2012 Realtek Corporation. */
3
4 #include "../include/osdep_service.h"
5 #include "../include/drv_types.h"
6 #include "../include/wlan_bssdef.h"
7 #include "../include/wifi.h"
8 #include "../include/rtw_mlme.h"
9 #include "../include/rtw_mlme_ext.h"
10 #include "../include/rtw_ioctl.h"
11 #include "../include/rtw_ioctl_set.h"
12 #include "../include/usb_ops.h"
13 #include "../include/rtl8188e_hal.h"
14 #include "../include/rtw_led.h"
15
16 #include "../include/rtw_iol.h"
17
18 #define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30)
19
20 #define SCAN_ITEM_SIZE 768
21 #define MAX_CUSTOM_LEN 64
22 #define RATE_COUNT 4
23
24 /* combo scan */
25 #define WEXT_CSCAN_AMOUNT 9
26 #define WEXT_CSCAN_BUF_LEN 360
27 #define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00"
28 #define WEXT_CSCAN_HEADER_SIZE 12
29 #define WEXT_CSCAN_SSID_SECTION 'S'
30 #define WEXT_CSCAN_CHANNEL_SECTION 'C'
31 #define WEXT_CSCAN_NPROBE_SECTION 'N'
32 #define WEXT_CSCAN_ACTV_DWELL_SECTION 'A'
33 #define WEXT_CSCAN_PASV_DWELL_SECTION 'P'
34 #define WEXT_CSCAN_HOME_DWELL_SECTION 'H'
35 #define WEXT_CSCAN_TYPE_SECTION 'T'
36
37 static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000,
38 6000000, 9000000, 12000000, 18000000, 24000000, 36000000,
39 48000000, 54000000};
40
indicate_wx_scan_complete_event(struct adapter * padapter)41 void indicate_wx_scan_complete_event(struct adapter *padapter)
42 {
43 union iwreq_data wrqu;
44
45 memset(&wrqu, 0, sizeof(union iwreq_data));
46 wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL);
47 }
48
rtw_indicate_wx_assoc_event(struct adapter * padapter)49 void rtw_indicate_wx_assoc_event(struct adapter *padapter)
50 {
51 union iwreq_data wrqu;
52 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
53
54 memset(&wrqu, 0, sizeof(union iwreq_data));
55
56 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
57
58 memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
59
60 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
61 }
62
rtw_indicate_wx_disassoc_event(struct adapter * padapter)63 void rtw_indicate_wx_disassoc_event(struct adapter *padapter)
64 {
65 union iwreq_data wrqu;
66
67 memset(&wrqu, 0, sizeof(union iwreq_data));
68
69 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
70 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
71
72 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
73 }
74
translate_scan(struct adapter * padapter,struct iw_request_info * info,struct wlan_network * pnetwork,char * start,char * stop)75 static char *translate_scan(struct adapter *padapter,
76 struct iw_request_info *info,
77 struct wlan_network *pnetwork,
78 char *start, char *stop)
79 {
80 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
81 struct iw_event iwe;
82 u16 cap;
83 __le16 le_tmp;
84 u32 ht_ielen = 0;
85 char *custom;
86 char *p;
87 u16 max_rate = 0, rate, ht_cap = false;
88 u32 i = 0;
89 u8 bw_40MHz = 0, short_GI = 0;
90 u16 mcs_rate = 0;
91 u8 ss, sq;
92 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
93
94 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
95 u32 blnGotP2PIE = false;
96
97 /* User is doing the P2P device discovery */
98 /* The prefix of SSID should be "DIRECT-" and the IE should contains the P2P IE. */
99 /* If not, the driver should ignore this AP and go to the next AP. */
100
101 /* Verifying the SSID */
102 if (!memcmp(pnetwork->network.Ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN)) {
103 u32 p2pielen = 0;
104
105 if (pnetwork->network.Reserved[0] == 2) {/* Probe Request */
106 /* Verifying the P2P IE */
107 if (rtw_get_p2p_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &p2pielen))
108 blnGotP2PIE = true;
109 } else {/* Beacon or Probe Respones */
110 /* Verifying the P2P IE */
111 if (rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen))
112 blnGotP2PIE = true;
113 }
114 }
115
116 if (!blnGotP2PIE)
117 return start;
118 }
119
120 /* AP MAC address */
121 iwe.cmd = SIOCGIWAP;
122 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
123
124 memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
125 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
126
127 /* Add the ESSID */
128 iwe.cmd = SIOCGIWESSID;
129 iwe.u.data.flags = 1;
130 iwe.u.data.length = min_t(u16, pnetwork->network.Ssid.SsidLength, 32);
131 start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
132
133 /* parsing HT_CAP_IE */
134 p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength - 12);
135
136 if (p && ht_ielen > 0) {
137 struct ieee80211_ht_cap *pht_capie;
138
139 ht_cap = true;
140 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
141 memcpy(&mcs_rate, pht_capie->mcs.rx_mask, 2);
142 bw_40MHz = (le16_to_cpu(pht_capie->cap_info) &
143 IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0;
144 short_GI = (le16_to_cpu(pht_capie->cap_info) &
145 (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
146 }
147
148 /* Add the protocol name */
149 iwe.cmd = SIOCGIWNAME;
150 if ((rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates))) {
151 if (ht_cap)
152 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
153 else
154 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
155 } else if ((rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates))) {
156 if (ht_cap)
157 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
158 else
159 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
160 } else {
161 if (ht_cap)
162 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
163 else
164 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
165 }
166
167 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
168
169 /* Add mode */
170 iwe.cmd = SIOCGIWMODE;
171 memcpy(&le_tmp, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
172
173 cap = le16_to_cpu(le_tmp);
174
175 if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
176 if (cap & WLAN_CAPABILITY_BSS)
177 iwe.u.mode = IW_MODE_MASTER;
178 else
179 iwe.u.mode = IW_MODE_ADHOC;
180
181 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
182 }
183
184 if (pnetwork->network.Configuration.DSConfig < 1)
185 pnetwork->network.Configuration.DSConfig = 1;
186
187 /* Add frequency/channel */
188 iwe.cmd = SIOCGIWFREQ;
189 iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
190 iwe.u.freq.e = 1;
191 iwe.u.freq.i = pnetwork->network.Configuration.DSConfig;
192 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
193
194 /* Add encryption capability */
195 iwe.cmd = SIOCGIWENCODE;
196 if (cap & WLAN_CAPABILITY_PRIVACY)
197 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
198 else
199 iwe.u.data.flags = IW_ENCODE_DISABLED;
200 iwe.u.data.length = 0;
201 start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
202
203 /*Add basic and extended rates */
204 max_rate = 0;
205 custom = kzalloc(MAX_CUSTOM_LEN, GFP_ATOMIC);
206 if (!custom)
207 return start;
208 p = custom;
209 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
210 while (pnetwork->network.SupportedRates[i] != 0) {
211 rate = pnetwork->network.SupportedRates[i] & 0x7F;
212 if (rate > max_rate)
213 max_rate = rate;
214 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
215 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
216 i++;
217 }
218
219 if (ht_cap) {
220 if (mcs_rate & 0x8000)/* MCS15 */
221 max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130);
222 else if (mcs_rate & 0x0080)/* MCS7 */
223 ;
224 else/* default MCS7 */
225 max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65);
226
227 max_rate = max_rate * 2;/* Mbps/2; */
228 }
229
230 iwe.cmd = SIOCGIWRATE;
231 iwe.u.bitrate.fixed = 0;
232 iwe.u.bitrate.disabled = 0;
233 iwe.u.bitrate.value = max_rate * 500000;
234 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
235
236 /* parsing WPA/WPA2 IE */
237 {
238 u8 *buf;
239 u8 *wpa_ie, *rsn_ie;
240 u16 wpa_len = 0, rsn_len = 0;
241 u8 *p;
242
243 buf = kzalloc(MAX_WPA_IE_LEN, GFP_ATOMIC);
244 if (!buf)
245 goto exit;
246 wpa_ie = kzalloc(255, GFP_ATOMIC);
247 if (!wpa_ie) {
248 kfree(buf);
249 goto exit;
250 }
251 rsn_ie = kzalloc(255, GFP_ATOMIC);
252 if (!rsn_ie) {
253 kfree(buf);
254 kfree(wpa_ie);
255 goto exit;
256 }
257 rtw_get_sec_ie(pnetwork->network.IEs, pnetwork->network.IELength, rsn_ie, &rsn_len, wpa_ie, &wpa_len);
258
259 if (wpa_len > 0) {
260 p = buf;
261 memset(buf, 0, MAX_WPA_IE_LEN);
262 p += sprintf(p, "wpa_ie =");
263 for (i = 0; i < wpa_len; i++)
264 p += sprintf(p, "%02x", wpa_ie[i]);
265
266 memset(&iwe, 0, sizeof(iwe));
267 iwe.cmd = IWEVCUSTOM;
268 iwe.u.data.length = strlen(buf);
269 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
270
271 memset(&iwe, 0, sizeof(iwe));
272 iwe.cmd = IWEVGENIE;
273 iwe.u.data.length = wpa_len;
274 start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie);
275 }
276 if (rsn_len > 0) {
277 p = buf;
278 memset(buf, 0, MAX_WPA_IE_LEN);
279 p += sprintf(p, "rsn_ie =");
280 for (i = 0; i < rsn_len; i++)
281 p += sprintf(p, "%02x", rsn_ie[i]);
282 memset(&iwe, 0, sizeof(iwe));
283 iwe.cmd = IWEVCUSTOM;
284 iwe.u.data.length = strlen(buf);
285 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
286
287 memset(&iwe, 0, sizeof(iwe));
288 iwe.cmd = IWEVGENIE;
289 iwe.u.data.length = rsn_len;
290 start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie);
291 }
292 kfree(buf);
293 kfree(wpa_ie);
294 kfree(rsn_ie);
295 }
296
297 {/* parsing WPS IE */
298 uint cnt = 0, total_ielen;
299 u8 *wpsie_ptr = NULL;
300 uint wps_ielen = 0;
301
302 u8 *ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
303 total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
304
305 while (cnt < total_ielen) {
306 if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) {
307 wpsie_ptr = &ie_ptr[cnt];
308 iwe.cmd = IWEVGENIE;
309 iwe.u.data.length = (u16)wps_ielen;
310 start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr);
311 }
312 cnt += ie_ptr[cnt + 1] + 2; /* goto next */
313 }
314 }
315
316 /* Add quality statistics */
317 iwe.cmd = IWEVQUAL;
318 iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID;
319
320 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
321 is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network)) {
322 ss = padapter->recvpriv.signal_strength;
323 sq = padapter->recvpriv.signal_qual;
324 } else {
325 ss = pnetwork->network.PhyInfo.SignalStrength;
326 sq = pnetwork->network.PhyInfo.SignalQuality;
327 }
328
329 iwe.u.qual.level = (u8)ss;
330 iwe.u.qual.qual = (u8)sq; /* signal quality */
331 iwe.u.qual.noise = 0; /* noise level */
332 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
333 exit:
334 kfree(custom);
335 return start;
336 }
337
wpa_set_auth_algs(struct net_device * dev,u32 value)338 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
339 {
340 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
341 int ret = 0;
342
343 if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
344 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
345 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
346 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
347 } else if (value & AUTH_ALG_SHARED_KEY) {
348 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
349
350 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
351 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
352 } else if (value & AUTH_ALG_OPEN_SYSTEM) {
353 if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
354 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
355 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
356 }
357 } else if (!(value & AUTH_ALG_LEAP)) {
358 ret = -EINVAL;
359 }
360 return ret;
361 }
362
wpa_set_encryption(struct net_device * dev,struct ieee_param * param,u32 param_len)363 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
364 {
365 int ret = 0;
366 u32 wep_key_idx, wep_key_len, wep_total_len;
367 struct ndis_802_11_wep *pwep = NULL;
368 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
369 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
370 struct security_priv *psecuritypriv = &padapter->securitypriv;
371 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
372
373 param->u.crypt.err = 0;
374 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
375
376 if (param_len < (u32)((u8 *)param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) {
377 ret = -EINVAL;
378 goto exit;
379 }
380
381 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
382 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
383 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
384 if (param->u.crypt.idx >= WEP_KEYS) {
385 ret = -EINVAL;
386 goto exit;
387 }
388 } else {
389 ret = -EINVAL;
390 goto exit;
391 }
392
393 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
394 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
395 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
396 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
397
398 wep_key_idx = param->u.crypt.idx;
399 wep_key_len = param->u.crypt.key_len;
400
401 if (wep_key_idx > WEP_KEYS)
402 return -EINVAL;
403
404 if (wep_key_len > 0) {
405 wep_key_len = wep_key_len <= 5 ? 5 : 13;
406 wep_total_len = wep_key_len + sizeof(*pwep);
407 pwep = kzalloc(wep_total_len, GFP_KERNEL);
408 if (!pwep)
409 goto exit;
410
411 pwep->KeyLength = wep_key_len;
412 pwep->Length = wep_total_len;
413 if (wep_key_len == 13) {
414 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
415 padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
416 }
417 } else {
418 ret = -EINVAL;
419 goto exit;
420 }
421 pwep->KeyIndex = wep_key_idx;
422 pwep->KeyIndex |= 0x80000000;
423 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
424 if (param->u.crypt.set_tx) {
425 if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
426 ret = -EOPNOTSUPP;
427 } else {
428 if (wep_key_idx >= WEP_KEYS) {
429 ret = -EOPNOTSUPP;
430 goto exit;
431 }
432 memcpy(&psecuritypriv->dot11DefKey[wep_key_idx].skey[0], pwep->KeyMaterial, pwep->KeyLength);
433 psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
434 rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0);
435 }
436 goto exit;
437 }
438
439 if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /* 802_1x */
440 struct sta_info *psta, *pbcmc_sta;
441 struct sta_priv *pstapriv = &padapter->stapriv;
442
443 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE)) { /* sta mode */
444 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
445 if (!psta) {
446 ;
447 } else {
448 if (strcmp(param->u.crypt.alg, "none") != 0)
449 psta->ieee8021x_blocked = false;
450
451 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
452 (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
453 psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
454
455 if (param->u.crypt.set_tx == 1) { /* pairwise key */
456 memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
457
458 if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
459 memcpy(psta->dot11tkiptxmickey.skey, ¶m->u.crypt.key[16], 8);
460 memcpy(psta->dot11tkiprxmickey.skey, ¶m->u.crypt.key[24], 8);
461 padapter->securitypriv.busetkipkey = false;
462 }
463
464 rtw_setstakey_cmd(padapter, (unsigned char *)psta, true);
465 } else { /* group key */
466 memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
467 memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, ¶m->u.crypt.key[16], 8);
468 memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, ¶m->u.crypt.key[24], 8);
469 padapter->securitypriv.binstallGrpkey = true;
470
471 padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
472
473 rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1);
474 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
475 rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_DONE);
476 }
477 }
478 pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
479 if (!pbcmc_sta) {
480 ;
481 } else {
482 /* Jeff: don't disable ieee8021x_blocked while clearing key */
483 if (strcmp(param->u.crypt.alg, "none") != 0)
484 pbcmc_sta->ieee8021x_blocked = false;
485
486 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
487 (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
488 pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
489 }
490 }
491 }
492
493 exit:
494
495 kfree(pwep);
496
497 return ret;
498 }
499
rtw_set_wpa_ie(struct adapter * padapter,char * pie,unsigned short ielen)500 static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen)
501 {
502 u8 *buf = NULL;
503 int group_cipher = 0, pairwise_cipher = 0;
504 int ret = 0;
505 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
506
507 if (ielen > MAX_WPA_IE_LEN || !pie) {
508 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
509 if (!pie)
510 return ret;
511 else
512 return -EINVAL;
513 }
514
515 if (ielen) {
516 buf = kmemdup(pie, ielen, GFP_KERNEL);
517 if (!buf) {
518 ret = -ENOMEM;
519 goto exit;
520 }
521
522 if (ielen < RSN_HEADER_LEN) {
523 ret = -1;
524 goto exit;
525 }
526
527 if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
528 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
529 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
530 memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
531 }
532
533 if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
534 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
535 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
536 memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
537 }
538
539 switch (group_cipher) {
540 case WPA_CIPHER_NONE:
541 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
542 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
543 break;
544 case WPA_CIPHER_WEP40:
545 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
546 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
547 break;
548 case WPA_CIPHER_TKIP:
549 padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
550 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
551 break;
552 case WPA_CIPHER_CCMP:
553 padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
554 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
555 break;
556 case WPA_CIPHER_WEP104:
557 padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
558 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
559 break;
560 }
561
562 switch (pairwise_cipher) {
563 case WPA_CIPHER_NONE:
564 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
565 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
566 break;
567 case WPA_CIPHER_WEP40:
568 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
569 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
570 break;
571 case WPA_CIPHER_TKIP:
572 padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
573 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
574 break;
575 case WPA_CIPHER_CCMP:
576 padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
577 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
578 break;
579 case WPA_CIPHER_WEP104:
580 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
581 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
582 break;
583 }
584
585 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
586 {/* set wps_ie */
587 u16 cnt = 0;
588 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
589
590 while (cnt < ielen) {
591 eid = buf[cnt];
592 if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&buf[cnt + 2], wps_oui, 4))) {
593 padapter->securitypriv.wps_ie_len = ((buf[cnt + 1] + 2) < (MAX_WPA_IE_LEN << 2)) ? (buf[cnt + 1] + 2) : (MAX_WPA_IE_LEN << 2);
594
595 memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
596
597 set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
598 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK))
599 rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_ING);
600 cnt += buf[cnt + 1] + 2;
601 break;
602 } else {
603 cnt += buf[cnt + 1] + 2; /* goto next */
604 }
605 }
606 }
607 }
608
609 exit:
610 kfree(buf);
611 return ret;
612 }
613
614 typedef unsigned char NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX];
615
rtw_wx_get_name(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)616 static int rtw_wx_get_name(struct net_device *dev,
617 struct iw_request_info *info,
618 union iwreq_data *wrqu, char *extra)
619 {
620 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
621 u32 ht_ielen = 0;
622 char *p;
623 u8 ht_cap = false;
624 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
625 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
626 NDIS_802_11_RATES_EX *prates = NULL;
627
628 if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
629 /* parsing HT_CAP_IE */
630 p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength - 12);
631 if (p && ht_ielen > 0)
632 ht_cap = true;
633
634 prates = &pcur_bss->SupportedRates;
635
636 if (rtw_is_cckratesonly_included((u8 *)prates)) {
637 if (ht_cap)
638 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
639 else
640 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
641 } else if (rtw_is_cckrates_included((u8 *)prates)) {
642 if (ht_cap)
643 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
644 else
645 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
646 } else {
647 if (ht_cap)
648 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
649 else
650 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
651 }
652 } else {
653 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
654 }
655
656
657
658 return 0;
659 }
660
rtw_wx_get_freq(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)661 static int rtw_wx_get_freq(struct net_device *dev,
662 struct iw_request_info *info,
663 union iwreq_data *wrqu, char *extra)
664 {
665 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
666 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
667 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
668
669 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
670 /* wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000; */
671 wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
672 wrqu->freq.e = 1;
673 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
674 } else {
675 wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
676 wrqu->freq.e = 1;
677 wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
678 }
679
680 return 0;
681 }
682
rtw_wx_set_mode(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * b)683 static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
684 union iwreq_data *wrqu, char *b)
685 {
686 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
687 enum ndis_802_11_network_infra networkType;
688 int ret = 0;
689
690 ret = rtw_pwr_wakeup(padapter);
691 if (ret)
692 goto exit;
693
694 if (!padapter->hw_init_completed) {
695 ret = -EPERM;
696 goto exit;
697 }
698
699 switch (wrqu->mode) {
700 case IW_MODE_AUTO:
701 networkType = Ndis802_11AutoUnknown;
702 break;
703 case IW_MODE_ADHOC:
704 networkType = Ndis802_11IBSS;
705 break;
706 case IW_MODE_MASTER:
707 networkType = Ndis802_11APMode;
708 break;
709 case IW_MODE_INFRA:
710 networkType = Ndis802_11Infrastructure;
711 break;
712 default:
713 ret = -EINVAL;
714 goto exit;
715 }
716 if (!rtw_set_802_11_infrastructure_mode(padapter, networkType)) {
717 ret = -EPERM;
718 goto exit;
719 }
720 rtw_setopmode_cmd(padapter, networkType);
721 exit:
722
723 return ret;
724 }
725
rtw_wx_get_mode(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * b)726 static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
727 union iwreq_data *wrqu, char *b)
728 {
729 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
730 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
731
732 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
733 wrqu->mode = IW_MODE_INFRA;
734 else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
735 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
736 wrqu->mode = IW_MODE_ADHOC;
737 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
738 wrqu->mode = IW_MODE_MASTER;
739 else
740 wrqu->mode = IW_MODE_AUTO;
741
742
743
744 return 0;
745 }
746
rtw_wx_set_pmkid(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * extra)747 static int rtw_wx_set_pmkid(struct net_device *dev,
748 struct iw_request_info *a,
749 union iwreq_data *wrqu, char *extra)
750 {
751 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
752 u8 j, blInserted = false;
753 int ret = false;
754 struct security_priv *psecuritypriv = &padapter->securitypriv;
755 struct iw_pmksa *pPMK = (struct iw_pmksa *)extra;
756 u8 strZeroMacAddress[ETH_ALEN] = {0x00};
757 u8 strIssueBssid[ETH_ALEN] = {0x00};
758
759 memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
760 if (pPMK->cmd == IW_PMKSA_ADD) {
761 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
762 return ret;
763 else
764 ret = true;
765 blInserted = false;
766
767 /* overwrite PMKID */
768 for (j = 0; j < NUM_PMKID_CACHE; j++) {
769 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
770 /* BSSID is matched, the same AP => rewrite with new PMKID. */
771 memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
772 psecuritypriv->PMKIDList[j].bUsed = true;
773 psecuritypriv->PMKIDIndex = j + 1;
774 blInserted = true;
775 break;
776 }
777 }
778
779 if (!blInserted) {
780 /* Find a new entry */
781 memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
782 memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
783
784 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = true;
785 psecuritypriv->PMKIDIndex++;
786 if (psecuritypriv->PMKIDIndex == 16)
787 psecuritypriv->PMKIDIndex = 0;
788 }
789 } else if (pPMK->cmd == IW_PMKSA_REMOVE) {
790 ret = true;
791 for (j = 0; j < NUM_PMKID_CACHE; j++) {
792 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
793 /* BSSID is matched, the same AP => Remove this PMKID information and reset it. */
794 memset(psecuritypriv->PMKIDList[j].Bssid, 0x00, ETH_ALEN);
795 psecuritypriv->PMKIDList[j].bUsed = false;
796 break;
797 }
798 }
799 } else if (pPMK->cmd == IW_PMKSA_FLUSH) {
800 memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
801 psecuritypriv->PMKIDIndex = 0;
802 ret = true;
803 }
804 return ret;
805 }
806
rtw_wx_get_sens(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)807 static int rtw_wx_get_sens(struct net_device *dev,
808 struct iw_request_info *info,
809 union iwreq_data *wrqu, char *extra)
810 {
811 wrqu->sens.value = 0;
812 wrqu->sens.fixed = 0; /* no auto select */
813 wrqu->sens.disabled = 1;
814 return 0;
815 }
816
rtw_wx_get_range(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)817 static int rtw_wx_get_range(struct net_device *dev,
818 struct iw_request_info *info,
819 union iwreq_data *wrqu, char *extra)
820 {
821 struct iw_range *range = (struct iw_range *)extra;
822 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
823 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
824
825 u16 val;
826 int i;
827
828 wrqu->data.length = sizeof(*range);
829 memset(range, 0, sizeof(*range));
830
831 /* Let's try to keep this struct in the same order as in
832 * linux/include/wireless.h
833 */
834
835 /* TODO: See what values we can set, and remove the ones we can't
836 * set, or fill them with some default data.
837 */
838
839 /* ~5 Mb/s real (802.11b) */
840 range->throughput = 5 * 1000 * 1000;
841
842 /* signal level threshold range */
843
844 /* percent values between 0 and 100. */
845 range->max_qual.qual = 100;
846 range->max_qual.level = 100;
847 range->max_qual.noise = 100;
848 range->max_qual.updated = 7; /* Updated all three */
849
850 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
851 /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
852 range->avg_qual.level = 178; /* -78 dBm */
853 range->avg_qual.noise = 0;
854 range->avg_qual.updated = 7; /* Updated all three */
855
856 range->num_bitrates = RATE_COUNT;
857
858 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
859 range->bitrate[i] = rtw_rates[i];
860
861 range->min_frag = MIN_FRAG_THRESHOLD;
862 range->max_frag = MAX_FRAG_THRESHOLD;
863
864 range->pm_capa = 0;
865
866 range->we_version_compiled = WIRELESS_EXT;
867 range->we_version_source = 16;
868
869 for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
870 /* Include only legal frequencies for some countries */
871 if (pmlmeext->channel_set[i].ChannelNum != 0) {
872 range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
873 range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
874 range->freq[val].e = 1;
875 val++;
876 }
877
878 if (val == IW_MAX_FREQUENCIES)
879 break;
880 }
881
882 range->num_channels = val;
883 range->num_frequency = val;
884
885 /* The following code will proivde the security capability to network manager. */
886 /* If the driver doesn't provide this capability to network manager, */
887 /* the WPA/WPA2 routers can't be chosen in the network manager. */
888
889 /*
890 #define IW_SCAN_CAPA_NONE 0x00
891 #define IW_SCAN_CAPA_ESSID 0x01
892 #define IW_SCAN_CAPA_BSSID 0x02
893 #define IW_SCAN_CAPA_CHANNEL 0x04
894 #define IW_SCAN_CAPA_MODE 0x08
895 #define IW_SCAN_CAPA_RATE 0x10
896 #define IW_SCAN_CAPA_TYPE 0x20
897 #define IW_SCAN_CAPA_TIME 0x40
898 */
899
900 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
901 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
902
903 range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE |
904 IW_SCAN_CAPA_BSSID | IW_SCAN_CAPA_CHANNEL |
905 IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE;
906
907
908 return 0;
909 }
910
911 /* set bssid flow */
912 /* s1. rtw_set_802_11_infrastructure_mode() */
913 /* s2. rtw_set_802_11_authentication_mode() */
914 /* s3. set_802_11_encryption_mode() */
915 /* s4. rtw_set_802_11_bssid() */
rtw_wx_set_wap(struct net_device * dev,struct iw_request_info * info,union iwreq_data * awrq,char * extra)916 static int rtw_wx_set_wap(struct net_device *dev,
917 struct iw_request_info *info,
918 union iwreq_data *awrq,
919 char *extra)
920 {
921 uint ret = 0;
922 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
923 struct sockaddr *temp = (struct sockaddr *)awrq;
924 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
925 struct list_head *phead;
926 u8 *dst_bssid, *src_bssid;
927 struct __queue *queue = &pmlmepriv->scanned_queue;
928 struct wlan_network *pnetwork = NULL;
929 enum ndis_802_11_auth_mode authmode;
930
931 ret = rtw_pwr_wakeup(padapter);
932 if (ret)
933 goto exit;
934
935 if (!padapter->bup) {
936 ret = -1;
937 goto exit;
938 }
939
940 if (temp->sa_family != ARPHRD_ETHER) {
941 ret = -EINVAL;
942 goto exit;
943 }
944
945 authmode = padapter->securitypriv.ndisauthtype;
946 spin_lock_bh(&queue->lock);
947 phead = get_list_head(queue);
948 pmlmepriv->pscanned = phead->next;
949
950 while (phead != pmlmepriv->pscanned) {
951
952 pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
953
954 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
955
956 dst_bssid = pnetwork->network.MacAddress;
957
958 src_bssid = temp->sa_data;
959
960 if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) {
961 if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
962 ret = -1;
963 spin_unlock_bh(&queue->lock);
964 goto exit;
965 }
966
967 break;
968 }
969 }
970 spin_unlock_bh(&queue->lock);
971
972 rtw_set_802_11_authentication_mode(padapter, authmode);
973 /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
974 if (!rtw_set_802_11_bssid(padapter, temp->sa_data)) {
975 ret = -1;
976 goto exit;
977 }
978
979 exit:
980
981
982
983 return ret;
984 }
985
rtw_wx_get_wap(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)986 static int rtw_wx_get_wap(struct net_device *dev,
987 struct iw_request_info *info,
988 union iwreq_data *wrqu, char *extra)
989 {
990 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
991 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
992 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
993
994 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
995
996 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
997
998 if (check_fwstate(pmlmepriv, _FW_LINKED) ||
999 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1000 check_fwstate(pmlmepriv, WIFI_AP_STATE))
1001 memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1002 else
1003 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1004
1005
1006
1007 return 0;
1008 }
1009
rtw_wx_set_mlme(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1010 static int rtw_wx_set_mlme(struct net_device *dev,
1011 struct iw_request_info *info,
1012 union iwreq_data *wrqu, char *extra)
1013 {
1014 int ret = 0;
1015 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1016 struct iw_mlme *mlme = (struct iw_mlme *)extra;
1017
1018 if (!mlme)
1019 return -1;
1020
1021 switch (mlme->cmd) {
1022 case IW_MLME_DEAUTH:
1023 if (!rtw_set_802_11_disassociate(padapter))
1024 ret = -1;
1025 break;
1026 case IW_MLME_DISASSOC:
1027 if (!rtw_set_802_11_disassociate(padapter))
1028 ret = -1;
1029 break;
1030 default:
1031 return -EOPNOTSUPP;
1032 }
1033 return ret;
1034 }
1035
rtw_wx_set_scan(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * extra)1036 static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
1037 union iwreq_data *wrqu, char *extra)
1038 {
1039 u8 _status = false;
1040 int ret = 0;
1041 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1042 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1043 struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
1044 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1045
1046 ret = rtw_pwr_wakeup(padapter);
1047 if (ret)
1048 goto exit;
1049
1050 if (padapter->bDriverStopped) {
1051 ret = -1;
1052 goto exit;
1053 }
1054
1055 if (!padapter->bup) {
1056 ret = -1;
1057 goto exit;
1058 }
1059
1060 if (!padapter->hw_init_completed) {
1061 ret = -1;
1062 goto exit;
1063 }
1064
1065 /* When Busy Traffic, driver do not site survey. So driver return success. */
1066 /* wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */
1067 /* modify by thomas 2011-02-22. */
1068 if (pmlmepriv->LinkDetectInfo.bBusyTraffic) {
1069 indicate_wx_scan_complete_event(padapter);
1070 goto exit;
1071 }
1072
1073 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) {
1074 indicate_wx_scan_complete_event(padapter);
1075 goto exit;
1076 }
1077
1078 /* For the DMP WiFi Display project, the driver won't to scan because */
1079 /* the pmlmepriv->scan_interval is always equal to 3. */
1080 /* So, the wpa_supplicant won't find out the WPS SoftAP. */
1081
1082 if (pwdinfo->p2p_state != P2P_STATE_NONE) {
1083 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
1084 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
1085 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_FULL);
1086 rtw_free_network_queue(padapter, true);
1087 }
1088
1089 memset(ssid, 0, sizeof(struct ndis_802_11_ssid) * RTW_SSID_SCAN_AMOUNT);
1090
1091 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1092 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1093
1094 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1095 int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE);
1096
1097 memcpy(ssid[0].Ssid, req->essid, len);
1098 ssid[0].SsidLength = len;
1099
1100 spin_lock_bh(&pmlmepriv->lock);
1101
1102 _status = rtw_sitesurvey_cmd(padapter, ssid, 1);
1103
1104 spin_unlock_bh(&pmlmepriv->lock);
1105 }
1106 } else {
1107 if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE &&
1108 !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
1109 int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE;
1110 char *pos = extra + WEXT_CSCAN_HEADER_SIZE;
1111 char section;
1112 char sec_len;
1113 int ssid_index = 0;
1114
1115 while (len >= 1) {
1116 section = *(pos++);
1117 len -= 1;
1118
1119 switch (section) {
1120 case WEXT_CSCAN_SSID_SECTION:
1121 if (len < 1) {
1122 len = 0;
1123 break;
1124 }
1125 sec_len = *(pos++); len -= 1;
1126 if (sec_len > 0 &&
1127 sec_len <= len &&
1128 sec_len <= 32) {
1129 ssid[ssid_index].SsidLength = sec_len;
1130 memcpy(ssid[ssid_index].Ssid, pos, sec_len);
1131 ssid_index++;
1132 }
1133 pos += sec_len;
1134 len -= sec_len;
1135 break;
1136 case WEXT_CSCAN_TYPE_SECTION:
1137 case WEXT_CSCAN_CHANNEL_SECTION:
1138 pos += 1;
1139 len -= 1;
1140 break;
1141 case WEXT_CSCAN_PASV_DWELL_SECTION:
1142 case WEXT_CSCAN_HOME_DWELL_SECTION:
1143 case WEXT_CSCAN_ACTV_DWELL_SECTION:
1144 pos += 2;
1145 len -= 2;
1146 break;
1147 default:
1148 len = 0; /* stop parsing */
1149 }
1150 }
1151
1152 /* it has still some scan parameter to parse, we only do this now... */
1153 _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
1154 } else {
1155 _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
1156 }
1157 }
1158
1159 if (!_status)
1160 ret = -1;
1161
1162 exit:
1163
1164 return ret;
1165 }
1166
rtw_wx_get_scan(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * extra)1167 static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
1168 union iwreq_data *wrqu, char *extra)
1169 {
1170 struct list_head *plist, *phead;
1171 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1172 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1173 struct __queue *queue = &pmlmepriv->scanned_queue;
1174 struct wlan_network *pnetwork = NULL;
1175 char *ev = extra;
1176 char *stop = ev + wrqu->data.length;
1177 u32 ret = 0;
1178 u32 cnt = 0;
1179 u32 wait_for_surveydone;
1180 int wait_status;
1181 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1182
1183 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
1184 /* P2P is enabled */
1185 wait_for_surveydone = 200;
1186 } else {
1187 /* P2P is disabled */
1188 wait_for_surveydone = 100;
1189 }
1190
1191 wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING;
1192
1193 while (check_fwstate(pmlmepriv, wait_status)) {
1194 msleep(30);
1195 cnt++;
1196 if (cnt > wait_for_surveydone)
1197 break;
1198 }
1199
1200 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1201
1202 phead = get_list_head(queue);
1203 plist = phead->next;
1204
1205 while (phead != plist) {
1206 if ((stop - ev) < SCAN_ITEM_SIZE) {
1207 ret = -E2BIG;
1208 break;
1209 }
1210
1211 pnetwork = container_of(plist, struct wlan_network, list);
1212
1213 /* report network only if the current channel set contains the channel to which this network belongs */
1214 if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0)
1215 ev = translate_scan(padapter, a, pnetwork, ev, stop);
1216
1217 plist = plist->next;
1218 }
1219
1220 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1221
1222 wrqu->data.length = ev - extra;
1223 wrqu->data.flags = 0;
1224
1225 return ret;
1226 }
1227
1228 /* set ssid flow */
1229 /* s1. rtw_set_802_11_infrastructure_mode() */
1230 /* s2. set_802_11_authenticaion_mode() */
1231 /* s3. set_802_11_encryption_mode() */
1232 /* s4. rtw_set_802_11_ssid() */
rtw_wx_set_essid(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * extra)1233 static int rtw_wx_set_essid(struct net_device *dev,
1234 struct iw_request_info *a,
1235 union iwreq_data *wrqu, char *extra)
1236 {
1237 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1238 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1239 struct __queue *queue = &pmlmepriv->scanned_queue;
1240 struct list_head *phead;
1241 struct wlan_network *pnetwork = NULL;
1242 enum ndis_802_11_auth_mode authmode;
1243 struct ndis_802_11_ssid ndis_ssid;
1244 u8 *dst_ssid, *src_ssid;
1245
1246 uint ret = 0, len;
1247
1248 ret = rtw_pwr_wakeup(padapter);
1249 if (ret)
1250 goto exit;
1251
1252 if (!padapter->bup) {
1253 ret = -1;
1254 goto exit;
1255 }
1256
1257 if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
1258 ret = -E2BIG;
1259 goto exit;
1260 }
1261
1262 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1263 ret = -1;
1264 goto exit;
1265 }
1266
1267 authmode = padapter->securitypriv.ndisauthtype;
1268 if (wrqu->essid.flags && wrqu->essid.length) {
1269 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
1270
1271 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1272 ndis_ssid.SsidLength = len;
1273 memcpy(ndis_ssid.Ssid, extra, len);
1274 src_ssid = ndis_ssid.Ssid;
1275
1276 spin_lock_bh(&queue->lock);
1277 phead = get_list_head(queue);
1278 pmlmepriv->pscanned = phead->next;
1279
1280 while (phead != pmlmepriv->pscanned) {
1281 pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
1282
1283 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1284
1285 dst_ssid = pnetwork->network.Ssid.Ssid;
1286
1287 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength)) &&
1288 (pnetwork->network.Ssid.SsidLength == ndis_ssid.SsidLength)) {
1289
1290 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1291 if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
1292 continue;
1293 }
1294
1295 if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
1296 ret = -1;
1297 spin_unlock_bh(&queue->lock);
1298 goto exit;
1299 }
1300
1301 break;
1302 }
1303 }
1304 spin_unlock_bh(&queue->lock);
1305 rtw_set_802_11_authentication_mode(padapter, authmode);
1306 if (!rtw_set_802_11_ssid(padapter, &ndis_ssid)) {
1307 ret = -1;
1308 goto exit;
1309 }
1310 }
1311
1312 exit:
1313 return ret;
1314 }
1315
rtw_wx_get_essid(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * extra)1316 static int rtw_wx_get_essid(struct net_device *dev,
1317 struct iw_request_info *a,
1318 union iwreq_data *wrqu, char *extra)
1319 {
1320 u32 len;
1321 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1322 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1323 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1324
1325 if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
1326 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) {
1327 len = pcur_bss->Ssid.SsidLength;
1328 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1329 } else {
1330 len = 0;
1331 *extra = 0;
1332 }
1333 wrqu->essid.length = len;
1334 wrqu->essid.flags = 1;
1335
1336 return 0;
1337 }
1338
rtw_wx_set_rate(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * extra)1339 static int rtw_wx_set_rate(struct net_device *dev,
1340 struct iw_request_info *a,
1341 union iwreq_data *wrqu, char *extra)
1342 {
1343 int i, ret = 0;
1344 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1345 u8 datarates[NumRates];
1346 u32 target_rate = wrqu->bitrate.value;
1347 u32 fixed = wrqu->bitrate.fixed;
1348 u32 ratevalue = 0;
1349 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1350
1351 if (target_rate == -1) {
1352 ratevalue = 11;
1353 goto set_rate;
1354 }
1355 target_rate = target_rate / 100000;
1356
1357 switch (target_rate) {
1358 case 10:
1359 ratevalue = 0;
1360 break;
1361 case 20:
1362 ratevalue = 1;
1363 break;
1364 case 55:
1365 ratevalue = 2;
1366 break;
1367 case 60:
1368 ratevalue = 3;
1369 break;
1370 case 90:
1371 ratevalue = 4;
1372 break;
1373 case 110:
1374 ratevalue = 5;
1375 break;
1376 case 120:
1377 ratevalue = 6;
1378 break;
1379 case 180:
1380 ratevalue = 7;
1381 break;
1382 case 240:
1383 ratevalue = 8;
1384 break;
1385 case 360:
1386 ratevalue = 9;
1387 break;
1388 case 480:
1389 ratevalue = 10;
1390 break;
1391 case 540:
1392 ratevalue = 11;
1393 break;
1394 default:
1395 ratevalue = 11;
1396 break;
1397 }
1398
1399 set_rate:
1400
1401 for (i = 0; i < NumRates; i++) {
1402 if (ratevalue == mpdatarate[i]) {
1403 datarates[i] = mpdatarate[i];
1404 if (fixed == 0)
1405 break;
1406 } else {
1407 datarates[i] = 0xff;
1408 }
1409 }
1410
1411 if (rtw_setdatarate_cmd(padapter, datarates) != _SUCCESS)
1412 ret = -1;
1413
1414 return ret;
1415 }
1416
rtw_wx_get_rate(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1417 static int rtw_wx_get_rate(struct net_device *dev,
1418 struct iw_request_info *info,
1419 union iwreq_data *wrqu, char *extra)
1420 {
1421 u16 max_rate = 0;
1422
1423 max_rate = rtw_get_cur_max_rate((struct adapter *)rtw_netdev_priv(dev));
1424
1425 if (max_rate == 0)
1426 return -EPERM;
1427
1428 wrqu->bitrate.fixed = 0; /* no auto select */
1429 wrqu->bitrate.value = max_rate * 100000;
1430
1431 return 0;
1432 }
1433
rtw_wx_set_rts(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1434 static int rtw_wx_set_rts(struct net_device *dev,
1435 struct iw_request_info *info,
1436 union iwreq_data *wrqu, char *extra)
1437 {
1438 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1439
1440
1441
1442 if (wrqu->rts.disabled) {
1443 padapter->registrypriv.rts_thresh = 2347;
1444 } else {
1445 if (wrqu->rts.value < 0 ||
1446 wrqu->rts.value > 2347)
1447 return -EINVAL;
1448
1449 padapter->registrypriv.rts_thresh = wrqu->rts.value;
1450 }
1451
1452 return 0;
1453 }
1454
rtw_wx_get_rts(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1455 static int rtw_wx_get_rts(struct net_device *dev,
1456 struct iw_request_info *info,
1457 union iwreq_data *wrqu, char *extra)
1458 {
1459 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1460
1461
1462
1463 wrqu->rts.value = padapter->registrypriv.rts_thresh;
1464 wrqu->rts.fixed = 0; /* no auto select */
1465 /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
1466
1467
1468
1469 return 0;
1470 }
1471
rtw_wx_set_frag(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1472 static int rtw_wx_set_frag(struct net_device *dev,
1473 struct iw_request_info *info,
1474 union iwreq_data *wrqu, char *extra)
1475 {
1476 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1477
1478
1479
1480 if (wrqu->frag.disabled) {
1481 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1482 } else {
1483 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1484 wrqu->frag.value > MAX_FRAG_THRESHOLD)
1485 return -EINVAL;
1486
1487 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1488 }
1489
1490 return 0;
1491 }
1492
rtw_wx_get_frag(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1493 static int rtw_wx_get_frag(struct net_device *dev,
1494 struct iw_request_info *info,
1495 union iwreq_data *wrqu, char *extra)
1496 {
1497 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1498
1499
1500
1501 wrqu->frag.value = padapter->xmitpriv.frag_len;
1502 wrqu->frag.fixed = 0; /* no auto select */
1503
1504
1505
1506 return 0;
1507 }
1508
rtw_wx_get_retry(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1509 static int rtw_wx_get_retry(struct net_device *dev,
1510 struct iw_request_info *info,
1511 union iwreq_data *wrqu, char *extra)
1512 {
1513 wrqu->retry.value = 7;
1514 wrqu->retry.fixed = 0; /* no auto select */
1515 wrqu->retry.disabled = 1;
1516
1517 return 0;
1518 }
1519
rtw_wx_set_enc(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * keybuf)1520 static int rtw_wx_set_enc(struct net_device *dev,
1521 struct iw_request_info *info,
1522 union iwreq_data *wrqu, char *keybuf)
1523 {
1524 u32 key, ret = 0;
1525 u32 keyindex_provided;
1526 struct ndis_802_11_wep wep;
1527 enum ndis_802_11_auth_mode authmode;
1528
1529 struct iw_point *erq = &wrqu->encoding;
1530 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1531 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
1532
1533 memset(&wep, 0, sizeof(struct ndis_802_11_wep));
1534
1535 key = erq->flags & IW_ENCODE_INDEX;
1536
1537
1538
1539 if (erq->flags & IW_ENCODE_DISABLED) {
1540 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1541 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1542 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1543 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1544 authmode = Ndis802_11AuthModeOpen;
1545 padapter->securitypriv.ndisauthtype = authmode;
1546
1547 goto exit;
1548 }
1549
1550 if (key) {
1551 if (key > WEP_KEYS)
1552 return -EINVAL;
1553 key--;
1554 keyindex_provided = 1;
1555 } else {
1556 keyindex_provided = 0;
1557 key = padapter->securitypriv.dot11PrivacyKeyIndex;
1558 }
1559
1560 /* set authentication mode */
1561 if (erq->flags & IW_ENCODE_OPEN) {
1562 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1563 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1564 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1565 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1566 authmode = Ndis802_11AuthModeOpen;
1567 padapter->securitypriv.ndisauthtype = authmode;
1568 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1569 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1570 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1571 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1572 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
1573 authmode = Ndis802_11AuthModeShared;
1574 padapter->securitypriv.ndisauthtype = authmode;
1575 } else {
1576 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1577 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1578 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1579 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1580 authmode = Ndis802_11AuthModeOpen;
1581 padapter->securitypriv.ndisauthtype = authmode;
1582 }
1583
1584 wep.KeyIndex = key;
1585 if (erq->length > 0) {
1586 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1587
1588 wep.Length = wep.KeyLength + offsetof(struct ndis_802_11_wep, KeyMaterial);
1589 } else {
1590 wep.KeyLength = 0;
1591
1592 if (keyindex_provided == 1) {
1593 /* set key_id only, no given KeyMaterial(erq->length == 0). */
1594 padapter->securitypriv.dot11PrivacyKeyIndex = key;
1595
1596 switch (padapter->securitypriv.dot11DefKeylen[key]) {
1597 case 5:
1598 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1599 break;
1600 case 13:
1601 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
1602 break;
1603 default:
1604 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1605 break;
1606 }
1607
1608 goto exit;
1609 }
1610 }
1611
1612 wep.KeyIndex |= 0x80000000;
1613
1614 memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1615
1616 if (!rtw_set_802_11_add_wep(padapter, &wep)) {
1617 if (rf_on == pwrpriv->rf_pwrstate)
1618 ret = -EOPNOTSUPP;
1619 goto exit;
1620 }
1621
1622 exit:
1623
1624
1625
1626 return ret;
1627 }
1628
rtw_wx_get_enc(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * keybuf)1629 static int rtw_wx_get_enc(struct net_device *dev,
1630 struct iw_request_info *info,
1631 union iwreq_data *wrqu, char *keybuf)
1632 {
1633 uint key;
1634 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1635 struct iw_point *erq = &wrqu->encoding;
1636 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1637
1638
1639
1640 if (check_fwstate(pmlmepriv, _FW_LINKED) != true) {
1641 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1642 erq->length = 0;
1643 erq->flags |= IW_ENCODE_DISABLED;
1644 return 0;
1645 }
1646 }
1647
1648 key = erq->flags & IW_ENCODE_INDEX;
1649
1650 if (key) {
1651 if (key > WEP_KEYS)
1652 return -EINVAL;
1653 key--;
1654 } else {
1655 key = padapter->securitypriv.dot11PrivacyKeyIndex;
1656 }
1657
1658 erq->flags = key + 1;
1659
1660 switch (padapter->securitypriv.ndisencryptstatus) {
1661 case Ndis802_11EncryptionNotSupported:
1662 case Ndis802_11EncryptionDisabled:
1663 erq->length = 0;
1664 erq->flags |= IW_ENCODE_DISABLED;
1665 break;
1666 case Ndis802_11Encryption1Enabled:
1667 erq->length = padapter->securitypriv.dot11DefKeylen[key];
1668 if (erq->length) {
1669 memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
1670
1671 erq->flags |= IW_ENCODE_ENABLED;
1672
1673 if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
1674 erq->flags |= IW_ENCODE_OPEN;
1675 else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
1676 erq->flags |= IW_ENCODE_RESTRICTED;
1677 } else {
1678 erq->length = 0;
1679 erq->flags |= IW_ENCODE_DISABLED;
1680 }
1681 break;
1682 case Ndis802_11Encryption2Enabled:
1683 case Ndis802_11Encryption3Enabled:
1684 erq->length = 16;
1685 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
1686 break;
1687 default:
1688 erq->length = 0;
1689 erq->flags |= IW_ENCODE_DISABLED;
1690 break;
1691 }
1692
1693
1694 return 0;
1695 }
1696
rtw_wx_get_power(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1697 static int rtw_wx_get_power(struct net_device *dev,
1698 struct iw_request_info *info,
1699 union iwreq_data *wrqu, char *extra)
1700 {
1701 wrqu->power.value = 0;
1702 wrqu->power.fixed = 0; /* no auto select */
1703 wrqu->power.disabled = 1;
1704
1705 return 0;
1706 }
1707
rtw_wx_set_gen_ie(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1708 static int rtw_wx_set_gen_ie(struct net_device *dev,
1709 struct iw_request_info *info,
1710 union iwreq_data *wrqu, char *extra)
1711 {
1712 int ret;
1713 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1714
1715 ret = rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
1716 return ret;
1717 }
1718
rtw_wx_set_auth(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1719 static int rtw_wx_set_auth(struct net_device *dev,
1720 struct iw_request_info *info,
1721 union iwreq_data *wrqu, char *extra)
1722 {
1723 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1724 struct iw_param *param = (struct iw_param *)&wrqu->param;
1725 int ret = 0;
1726
1727 switch (param->flags & IW_AUTH_INDEX) {
1728 case IW_AUTH_WPA_VERSION:
1729 break;
1730 case IW_AUTH_CIPHER_PAIRWISE:
1731
1732 break;
1733 case IW_AUTH_CIPHER_GROUP:
1734
1735 break;
1736 case IW_AUTH_KEY_MGMT:
1737 /*
1738 * ??? does not use these parameters
1739 */
1740 break;
1741 case IW_AUTH_TKIP_COUNTERMEASURES:
1742 if (param->value) {
1743 /* wpa_supplicant is enabling the tkip countermeasure. */
1744 padapter->securitypriv.btkip_countermeasure = true;
1745 } else {
1746 /* wpa_supplicant is disabling the tkip countermeasure. */
1747 padapter->securitypriv.btkip_countermeasure = false;
1748 }
1749 break;
1750 case IW_AUTH_DROP_UNENCRYPTED:
1751 /* HACK:
1752 *
1753 * wpa_supplicant calls set_wpa_enabled when the driver
1754 * is loaded and unloaded, regardless of if WPA is being
1755 * used. No other calls are made which can be used to
1756 * determine if encryption will be used or not prior to
1757 * association being expected. If encryption is not being
1758 * used, drop_unencrypted is set to false, else true -- we
1759 * can use this to determine if the CAP_PRIVACY_ON bit should
1760 * be set.
1761 */
1762
1763 if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled)
1764 break;/* it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled, */
1765 /* then it needn't reset it; */
1766
1767 if (param->value) {
1768 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1769 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1770 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1771 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1772 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
1773 }
1774
1775 break;
1776 case IW_AUTH_80211_AUTH_ALG:
1777 /*
1778 * It's the starting point of a link layer connection using wpa_supplicant
1779 */
1780 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
1781 LeaveAllPowerSaveMode(padapter);
1782 rtw_disassoc_cmd(padapter, 500, false);
1783 rtw_indicate_disconnect(padapter);
1784 rtw_free_assoc_resources(padapter, 1);
1785 }
1786 ret = wpa_set_auth_algs(dev, (u32)param->value);
1787 break;
1788 case IW_AUTH_WPA_ENABLED:
1789 break;
1790 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1791 break;
1792 case IW_AUTH_PRIVACY_INVOKED:
1793 break;
1794 default:
1795 return -EOPNOTSUPP;
1796 }
1797
1798 return ret;
1799 }
1800
rtw_wx_set_enc_ext(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1801 static int rtw_wx_set_enc_ext(struct net_device *dev,
1802 struct iw_request_info *info,
1803 union iwreq_data *wrqu, char *extra)
1804 {
1805 char *alg_name;
1806 u32 param_len;
1807 struct ieee_param *param = NULL;
1808 struct iw_point *pencoding = &wrqu->encoding;
1809 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
1810 int ret = -1;
1811
1812 param_len = sizeof(struct ieee_param) + pext->key_len;
1813 param = kzalloc(param_len, GFP_KERNEL);
1814 if (!param)
1815 return -ENOMEM;
1816
1817 param->cmd = IEEE_CMD_SET_ENCRYPTION;
1818 memset(param->sta_addr, 0xff, ETH_ALEN);
1819
1820 switch (pext->alg) {
1821 case IW_ENCODE_ALG_NONE:
1822 /* todo: remove key */
1823 /* remove = 1; */
1824 alg_name = "none";
1825 break;
1826 case IW_ENCODE_ALG_WEP:
1827 alg_name = "WEP";
1828 break;
1829 case IW_ENCODE_ALG_TKIP:
1830 alg_name = "TKIP";
1831 break;
1832 case IW_ENCODE_ALG_CCMP:
1833 alg_name = "CCMP";
1834 break;
1835 default:
1836 goto out;
1837 }
1838
1839 strscpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1840
1841 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1842 param->u.crypt.set_tx = 1;
1843
1844 /* cliW: WEP does not have group key
1845 * just not checking GROUP key setting
1846 */
1847 if ((pext->alg != IW_ENCODE_ALG_WEP) &&
1848 (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY))
1849 param->u.crypt.set_tx = 0;
1850
1851 param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
1852
1853 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1854 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
1855
1856 if (pext->key_len) {
1857 param->u.crypt.key_len = pext->key_len;
1858 memcpy(param->u.crypt.key, pext + 1, pext->key_len);
1859 }
1860
1861 ret = wpa_set_encryption(dev, param, param_len);
1862
1863 out:
1864 kfree(param);
1865 return ret;
1866 }
1867
rtw_wx_get_nick(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1868 static int rtw_wx_get_nick(struct net_device *dev,
1869 struct iw_request_info *info,
1870 union iwreq_data *wrqu, char *extra)
1871 {
1872 if (extra) {
1873 wrqu->data.length = 14;
1874 wrqu->data.flags = 1;
1875 memcpy(extra, "<WIFI@REALTEK>", 14);
1876 }
1877
1878 /* dump debug info here */
1879 return 0;
1880 }
1881
rtw_wx_read_rf(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1882 static int rtw_wx_read_rf(struct net_device *dev,
1883 struct iw_request_info *info,
1884 union iwreq_data *wrqu, char *extra)
1885 {
1886 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1887 u32 path, addr, data32;
1888
1889 path = *(u32 *)extra;
1890 if (path != RF_PATH_A)
1891 return -EINVAL;
1892
1893 addr = *((u32 *)extra + 1);
1894 data32 = rtl8188e_PHY_QueryRFReg(padapter, addr, 0xFFFFF);
1895 /*
1896 * IMPORTANT!!
1897 * Only when wireless private ioctl is at odd order,
1898 * "extra" would be copied to user space.
1899 */
1900 sprintf(extra, "0x%05x", data32);
1901
1902 return 0;
1903 }
1904
rtw_wx_write_rf(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1905 static int rtw_wx_write_rf(struct net_device *dev,
1906 struct iw_request_info *info,
1907 union iwreq_data *wrqu, char *extra)
1908 {
1909 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1910 u32 path, addr, data32;
1911
1912 path = *(u32 *)extra;
1913 if (path != RF_PATH_A)
1914 return -EINVAL;
1915
1916 addr = *((u32 *)extra + 1);
1917 data32 = *((u32 *)extra + 2);
1918 rtl8188e_PHY_SetRFReg(padapter, addr, 0xFFFFF, data32);
1919
1920 return 0;
1921 }
1922
rtw_wx_set_channel_plan(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1923 static int rtw_wx_set_channel_plan(struct net_device *dev,
1924 struct iw_request_info *info,
1925 union iwreq_data *wrqu, char *extra)
1926 {
1927 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1928 u8 channel_plan_req = (u8)(*((int *)wrqu));
1929
1930 if (rtw_set_chplan_cmd(padapter, channel_plan_req) != _SUCCESS)
1931 return -EPERM;
1932
1933 return 0;
1934 }
1935
rtw_get_ap_info(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1936 static int rtw_get_ap_info(struct net_device *dev,
1937 struct iw_request_info *info,
1938 union iwreq_data *wrqu, char *extra)
1939 {
1940 int ret = 0;
1941 u32 cnt = 0, wpa_ielen;
1942 struct list_head *plist, *phead;
1943 unsigned char *pbuf;
1944 u8 bssid[ETH_ALEN];
1945 char data[32];
1946 struct wlan_network *pnetwork = NULL;
1947 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1948 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1949 struct __queue *queue = &pmlmepriv->scanned_queue;
1950 struct iw_point *pdata = &wrqu->data;
1951
1952 if (padapter->bDriverStopped || !pdata) {
1953 ret = -EINVAL;
1954 goto exit;
1955 }
1956
1957 while ((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY | _FW_UNDER_LINKING)))) {
1958 msleep(30);
1959 cnt++;
1960 if (cnt > 100)
1961 break;
1962 }
1963 pdata->flags = 0;
1964 if (pdata->length >= 32) {
1965 if (copy_from_user(data, pdata->pointer, 32)) {
1966 ret = -EINVAL;
1967 goto exit;
1968 }
1969 } else {
1970 ret = -EINVAL;
1971 goto exit;
1972 }
1973
1974 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1975
1976 phead = get_list_head(queue);
1977 plist = phead->next;
1978
1979 while (phead != plist) {
1980 pnetwork = container_of(plist, struct wlan_network, list);
1981
1982 if (!mac_pton(data, bssid)) {
1983 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1984 return -EINVAL;
1985 }
1986
1987 if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
1988 /* BSSID match, then check if supporting wpa/wpa2 */
1989 pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength - 12);
1990 if (pbuf && (wpa_ielen > 0)) {
1991 pdata->flags = 1;
1992 break;
1993 }
1994
1995 pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength - 12);
1996 if (pbuf && (wpa_ielen > 0)) {
1997 pdata->flags = 2;
1998 break;
1999 }
2000 }
2001
2002 plist = plist->next;
2003 }
2004
2005 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
2006
2007 if (pdata->length >= 34) {
2008 if (copy_to_user(pdata->pointer + 32, (u8 *)&pdata->flags, 1)) {
2009 ret = -EINVAL;
2010 goto exit;
2011 }
2012 }
2013
2014 exit:
2015
2016 return ret;
2017 }
2018
rtw_set_pid(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2019 static int rtw_set_pid(struct net_device *dev,
2020 struct iw_request_info *info,
2021 union iwreq_data *wrqu, char *extra)
2022 {
2023 int ret = 0;
2024 struct adapter *padapter = rtw_netdev_priv(dev);
2025 int *pdata = (int *)wrqu;
2026 int selector;
2027
2028 if (padapter->bDriverStopped || !pdata) {
2029 ret = -EINVAL;
2030 goto exit;
2031 }
2032
2033 selector = *pdata;
2034 if (selector < 3 && selector >= 0) {
2035 padapter->pid[selector] = *(pdata + 1);
2036 ui_pid[selector] = *(pdata + 1);
2037 }
2038 exit:
2039 return ret;
2040 }
2041
rtw_wps_start(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2042 static int rtw_wps_start(struct net_device *dev,
2043 struct iw_request_info *info,
2044 union iwreq_data *wrqu, char *extra)
2045 {
2046 int ret = 0;
2047 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2048 struct iw_point *pdata = &wrqu->data;
2049 u32 u32wps_start = 0;
2050
2051 if (!pdata)
2052 return -EINVAL;
2053 ret = copy_from_user((void *)&u32wps_start, pdata->pointer, 4);
2054 if (ret) {
2055 ret = -EINVAL;
2056 goto exit;
2057 }
2058
2059 if (padapter->bDriverStopped) {
2060 ret = -EINVAL;
2061 goto exit;
2062 }
2063
2064 if (u32wps_start == 0)
2065 u32wps_start = *extra;
2066
2067 if (u32wps_start == 1) /* WPS Start */
2068 rtw_led_control(padapter, LED_CTL_START_WPS);
2069 else if (u32wps_start == 2) /* WPS Stop because of wps success */
2070 rtw_led_control(padapter, LED_CTL_STOP_WPS);
2071 else if (u32wps_start == 3) /* WPS Stop because of wps fail */
2072 rtw_led_control(padapter, LED_CTL_STOP_WPS_FAIL);
2073
2074 exit:
2075 return ret;
2076 }
2077
rtw_wext_p2p_enable(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2078 static int rtw_wext_p2p_enable(struct net_device *dev,
2079 struct iw_request_info *info,
2080 union iwreq_data *wrqu, char *extra)
2081 {
2082 int ret;
2083 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2084 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2085 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2086 enum P2P_ROLE init_role = P2P_ROLE_DISABLE;
2087
2088 if (*extra == '0')
2089 init_role = P2P_ROLE_DISABLE;
2090 else if (*extra == '1')
2091 init_role = P2P_ROLE_DEVICE;
2092 else if (*extra == '2')
2093 init_role = P2P_ROLE_CLIENT;
2094 else if (*extra == '3')
2095 init_role = P2P_ROLE_GO;
2096
2097 ret = rtw_p2p_enable(padapter, init_role);
2098 if (ret)
2099 return ret;
2100
2101 /* set channel/bandwidth */
2102 if (init_role != P2P_ROLE_DISABLE) {
2103 u8 channel, ch_offset;
2104 u16 bwmode;
2105
2106 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN)) {
2107 /* Stay at the listen state and wait for discovery. */
2108 channel = pwdinfo->listen_channel;
2109 pwdinfo->operating_channel = pwdinfo->listen_channel;
2110 ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2111 bwmode = HT_CHANNEL_WIDTH_20;
2112 } else {
2113 pwdinfo->operating_channel = pmlmeext->cur_channel;
2114
2115 channel = pwdinfo->operating_channel;
2116 ch_offset = pmlmeext->cur_ch_offset;
2117 bwmode = pmlmeext->cur_bwmode;
2118 }
2119
2120 set_channel_bwmode(padapter, channel, ch_offset, bwmode);
2121 }
2122
2123 return 0;
2124 }
2125
rtw_p2p_set_go_nego_ssid(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2126 static void rtw_p2p_set_go_nego_ssid(struct net_device *dev,
2127 struct iw_request_info *info,
2128 union iwreq_data *wrqu, char *extra)
2129 {
2130 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2131 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2132
2133 memcpy(pwdinfo->nego_ssid, extra, strlen(extra));
2134 pwdinfo->nego_ssidlen = strlen(extra);
2135 }
2136
rtw_p2p_set_intent(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2137 static int rtw_p2p_set_intent(struct net_device *dev,
2138 struct iw_request_info *info,
2139 union iwreq_data *wrqu, char *extra)
2140 {
2141 int ret = 0;
2142 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2143 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2144 u8 intent = pwdinfo->intent;
2145
2146 switch (wrqu->data.length) {
2147 case 1:
2148 intent = extra[0] - '0';
2149 break;
2150 case 2:
2151 intent = str_2char2num(extra[0], extra[1]);
2152 break;
2153 }
2154 if (intent <= 15)
2155 pwdinfo->intent = intent;
2156 else
2157 ret = -1;
2158 return ret;
2159 }
2160
rtw_p2p_set_listen_ch(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2161 static int rtw_p2p_set_listen_ch(struct net_device *dev,
2162 struct iw_request_info *info,
2163 union iwreq_data *wrqu, char *extra)
2164 {
2165 int ret = 0;
2166 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2167 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2168 u8 listen_ch = pwdinfo->listen_channel; /* Listen channel number */
2169
2170 switch (wrqu->data.length) {
2171 case 1:
2172 listen_ch = extra[0] - '0';
2173 break;
2174 case 2:
2175 listen_ch = str_2char2num(extra[0], extra[1]);
2176 break;
2177 }
2178
2179 if ((listen_ch == 1) || (listen_ch == 6) || (listen_ch == 11)) {
2180 pwdinfo->listen_channel = listen_ch;
2181 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
2182 } else {
2183 ret = -1;
2184 }
2185
2186 return ret;
2187 }
2188
rtw_p2p_set_op_ch(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2189 static int rtw_p2p_set_op_ch(struct net_device *dev,
2190 struct iw_request_info *info,
2191 union iwreq_data *wrqu, char *extra)
2192 {
2193 /* Commented by Albert 20110524 */
2194 /* This function is used to set the operating channel if the driver will become the group owner */
2195
2196 int ret = 0;
2197 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2198 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2199 u8 op_ch = pwdinfo->operating_channel; /* Operating channel number */
2200
2201 switch (wrqu->data.length) {
2202 case 1:
2203 op_ch = extra[0] - '0';
2204 break;
2205 case 2:
2206 op_ch = str_2char2num(extra[0], extra[1]);
2207 break;
2208 }
2209
2210 if (op_ch > 0)
2211 pwdinfo->operating_channel = op_ch;
2212 else
2213 ret = -1;
2214
2215 return ret;
2216 }
2217
rtw_p2p_profilefound(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2218 static int rtw_p2p_profilefound(struct net_device *dev,
2219 struct iw_request_info *info,
2220 union iwreq_data *wrqu, char *extra)
2221 {
2222 int ret = 0;
2223 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2224 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2225
2226 /* Comment by Albert 2010/10/13 */
2227 /* Input data format: */
2228 /* Ex: 0 */
2229 /* Ex: 1XX:XX:XX:XX:XX:XXYYSSID */
2230 /* 0 => Reflush the profile record list. */
2231 /* 1 => Add the profile list */
2232 /* XX:XX:XX:XX:XX:XX => peer's MAC Address (ex: 00:E0:4C:00:00:01) */
2233 /* YY => SSID Length */
2234 /* SSID => SSID for persistence group */
2235
2236 /* The upper application should pass the SSID to driver by using this rtw_p2p_profilefound function. */
2237 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
2238 if (extra[0] == '0') {
2239 /* Remove all the profile information of wifidirect_info structure. */
2240 memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
2241 pwdinfo->profileindex = 0;
2242 } else {
2243 if (pwdinfo->profileindex >= P2P_MAX_PERSISTENT_GROUP_NUM) {
2244 ret = -1;
2245 } else {
2246 int jj, kk;
2247
2248 /* Add this profile information into pwdinfo->profileinfo */
2249 /* Ex: 1XX:XX:XX:XX:XX:XXYYSSID */
2250 for (jj = 0, kk = 1; jj < ETH_ALEN; jj++, kk += 3)
2251 pwdinfo->profileinfo[pwdinfo->profileindex].peermac[jj] = key_2char2num(extra[kk], extra[kk + 1]);
2252
2253 pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen = (extra[18] - '0') * 10 + (extra[19] - '0');
2254 memcpy(pwdinfo->profileinfo[pwdinfo->profileindex].ssid, &extra[20], pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen);
2255 pwdinfo->profileindex++;
2256 }
2257 }
2258 }
2259
2260 return ret;
2261 }
2262
rtw_p2p_setDN(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2263 static void rtw_p2p_setDN(struct net_device *dev,
2264 struct iw_request_info *info,
2265 union iwreq_data *wrqu, char *extra)
2266 {
2267 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2268 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2269
2270 memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
2271 memcpy(pwdinfo->device_name, extra, wrqu->data.length - 1);
2272 pwdinfo->device_name_len = wrqu->data.length - 1;
2273 }
2274
rtw_p2p_get_wps_configmethod(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2275 static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
2276 struct iw_request_info *info,
2277 union iwreq_data *wrqu, char *extra)
2278 {
2279 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2280 u8 peerMAC[ETH_ALEN] = {0x00};
2281 int jj, kk;
2282 u8 peerMACStr[17] = {0x00};
2283 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2284 struct list_head *plist, *phead;
2285 struct __queue *queue = &pmlmepriv->scanned_queue;
2286 struct wlan_network *pnetwork = NULL;
2287 u8 blnMatch = 0;
2288 u16 attr_content = 0;
2289 uint attr_contentlen = 0;
2290 /* 6 is the string "wpsCM =", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */
2291 u8 attr_content_str[6 + 17] = {0x00};
2292
2293 /* Commented by Albert 20110727 */
2294 /* The input data is the MAC address which the application wants to know its WPS config method. */
2295 /* After knowing its WPS config method, the application can decide the config method for provisioning discovery. */
2296 /* Format: iwpriv wlanx p2p_get_wpsCM 00:E0:4C:00:00:05 */
2297
2298 if (copy_from_user(peerMACStr, wrqu->data.pointer + 6, 17))
2299 return -EFAULT;
2300
2301 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
2302 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
2303
2304 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
2305
2306 phead = get_list_head(queue);
2307 plist = phead->next;
2308
2309 while (phead != plist) {
2310 pnetwork = container_of(plist, struct wlan_network, list);
2311 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
2312 u8 *wpsie;
2313 uint wpsie_len = 0;
2314 __be16 be_tmp;
2315
2316 /* The mac address is matched. */
2317 wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len);
2318 if (wpsie) {
2319 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *)&be_tmp, &attr_contentlen);
2320 if (attr_contentlen) {
2321 attr_content = be16_to_cpu(be_tmp);
2322 sprintf(attr_content_str, "\n\nM =%.4d", attr_content);
2323 blnMatch = 1;
2324 }
2325 }
2326 break;
2327 }
2328 plist = plist->next;
2329 }
2330
2331 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
2332
2333 if (!blnMatch)
2334 sprintf(attr_content_str, "\n\nM = 0000");
2335
2336 if (copy_to_user(wrqu->data.pointer, attr_content_str, 6 + 17))
2337 return -EFAULT;
2338 return 0;
2339 }
2340
rtw_p2p_get_go_device_address(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2341 static int rtw_p2p_get_go_device_address(struct net_device *dev,
2342 struct iw_request_info *info,
2343 union iwreq_data *wrqu, char *extra)
2344 {
2345 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2346 u8 peerMAC[ETH_ALEN] = {0x00};
2347 int jj, kk;
2348 u8 peerMACStr[17] = {0x00};
2349 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2350 struct list_head *plist, *phead;
2351 struct __queue *queue = &pmlmepriv->scanned_queue;
2352 struct wlan_network *pnetwork = NULL;
2353 u8 blnMatch = 0;
2354 u8 *p2pie;
2355 uint p2pielen = 0, attr_contentlen = 0;
2356 u8 attr_content[100] = {0x00};
2357
2358 u8 go_devadd_str[100 + 10] = {0x00};
2359 /* +10 is for the str "go_devadd =", we have to clear it at wrqu->data.pointer */
2360
2361 /* Commented by Albert 20121209 */
2362 /* The input data is the GO's interface address which the application wants to know its device address. */
2363 /* Format: iwpriv wlanx p2p_get2 go_devadd = 00:E0:4C:00:00:05 */
2364
2365 if (copy_from_user(peerMACStr, wrqu->data.pointer + 10, 17))
2366 return -EFAULT;
2367
2368 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
2369 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
2370
2371 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
2372
2373 phead = get_list_head(queue);
2374 plist = phead->next;
2375
2376 while (phead != plist) {
2377 pnetwork = container_of(plist, struct wlan_network, list);
2378 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
2379 /* Commented by Albert 2011/05/18 */
2380 /* Match the device address located in the P2P IE */
2381 /* This is for the case that the P2P device address is not the same as the P2P interface address. */
2382
2383 p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
2384 if (p2pie) {
2385 while (p2pie) {
2386 /* The P2P Device ID attribute is included in the Beacon frame. */
2387 /* The P2P Device Info attribute is included in the probe response frame. */
2388
2389 memset(attr_content, 0x00, 100);
2390 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
2391 /* Handle the P2P Device ID attribute of Beacon first */
2392 blnMatch = 1;
2393 break;
2394 } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
2395 /* Handle the P2P Device Info attribute of probe response */
2396 blnMatch = 1;
2397 break;
2398 }
2399
2400 /* Get the next P2P IE */
2401 p2pie = rtw_get_p2p_ie(p2pie + p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
2402 }
2403 }
2404 }
2405
2406 plist = plist->next;
2407 }
2408
2409 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
2410
2411 if (!blnMatch)
2412 sprintf(go_devadd_str, "\n\ndev_add = NULL");
2413 else
2414 sprintf(go_devadd_str, "\ndev_add =%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
2415 attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]);
2416
2417 if (copy_to_user(wrqu->data.pointer, go_devadd_str, 10 + 17))
2418 return -EFAULT;
2419 return 0;
2420 }
2421
rtw_p2p_get_device_type(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2422 static int rtw_p2p_get_device_type(struct net_device *dev,
2423 struct iw_request_info *info,
2424 union iwreq_data *wrqu, char *extra)
2425 {
2426 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2427 u8 peerMAC[ETH_ALEN] = {0x00};
2428 int jj, kk;
2429 u8 peerMACStr[17] = {0x00};
2430 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2431 struct list_head *plist, *phead;
2432 struct __queue *queue = &pmlmepriv->scanned_queue;
2433 struct wlan_network *pnetwork = NULL;
2434 u8 blnMatch = 0;
2435 u8 dev_type[8] = {0x00};
2436 uint dev_type_len = 0;
2437 u8 dev_type_str[17 + 9] = {0x00}; /* +9 is for the str "dev_type =", we have to clear it at wrqu->data.pointer */
2438
2439 /* Commented by Albert 20121209 */
2440 /* The input data is the MAC address which the application wants to know its device type. */
2441 /* Such user interface could know the device type. */
2442 /* Format: iwpriv wlanx p2p_get2 dev_type = 00:E0:4C:00:00:05 */
2443
2444 if (copy_from_user(peerMACStr, wrqu->data.pointer + 9, 17))
2445 return -EFAULT;
2446
2447 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
2448 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
2449
2450 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
2451
2452 phead = get_list_head(queue);
2453 plist = phead->next;
2454
2455 while (phead != plist) {
2456 pnetwork = container_of(plist, struct wlan_network, list);
2457 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
2458 u8 *wpsie;
2459 uint wpsie_len = 0;
2460
2461 /* The mac address is matched. */
2462
2463 wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12],
2464 pnetwork->network.IELength - 12,
2465 NULL, &wpsie_len);
2466 if (wpsie) {
2467 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_PRIMARY_DEV_TYPE, dev_type, &dev_type_len);
2468 if (dev_type_len) {
2469 u16 type = 0;
2470 __be16 be_tmp;
2471
2472 memcpy(&be_tmp, dev_type, 2);
2473 type = be16_to_cpu(be_tmp);
2474 sprintf(dev_type_str, "\n\nN =%.2d", type);
2475 blnMatch = 1;
2476 }
2477 }
2478 break;
2479 }
2480
2481 plist = plist->next;
2482 }
2483
2484 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
2485
2486 if (!blnMatch)
2487 sprintf(dev_type_str, "\n\nN = 00");
2488
2489 if (copy_to_user(wrqu->data.pointer, dev_type_str, 9 + 17)) {
2490 return -EFAULT;
2491 }
2492
2493 return 0;
2494 }
2495
rtw_p2p_get_device_name(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2496 static int rtw_p2p_get_device_name(struct net_device *dev,
2497 struct iw_request_info *info,
2498 union iwreq_data *wrqu, char *extra)
2499 {
2500 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2501 u8 peerMAC[ETH_ALEN] = {0x00};
2502 int jj, kk;
2503 u8 peerMACStr[17] = {0x00};
2504 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2505 struct list_head *plist, *phead;
2506 struct __queue *queue = &pmlmepriv->scanned_queue;
2507 struct wlan_network *pnetwork = NULL;
2508 u8 blnMatch = 0;
2509 u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = {0x00};
2510 uint dev_len = 0;
2511 u8 dev_name_str[WPS_MAX_DEVICE_NAME_LEN + 5] = {0x00}; /* +5 is for the str "devN =", we have to clear it at wrqu->data.pointer */
2512
2513 /* Commented by Albert 20121225 */
2514 /* The input data is the MAC address which the application wants to know its device name. */
2515 /* Such user interface could show peer device's device name instead of ssid. */
2516 /* Format: iwpriv wlanx p2p_get2 devN = 00:E0:4C:00:00:05 */
2517
2518 if (copy_from_user(peerMACStr, wrqu->data.pointer + 5, 17))
2519 return -EFAULT;
2520
2521 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
2522 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
2523
2524 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
2525
2526 phead = get_list_head(queue);
2527 plist = phead->next;
2528
2529 while (phead != plist) {
2530 pnetwork = container_of(plist, struct wlan_network, list);
2531 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
2532 u8 *wpsie;
2533 uint wpsie_len = 0;
2534
2535 /* The mac address is matched. */
2536 wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len);
2537 if (wpsie) {
2538 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len);
2539 if (dev_len) {
2540 sprintf(dev_name_str, "\n\nN =%s", dev_name);
2541 blnMatch = 1;
2542 }
2543 }
2544 break;
2545 }
2546
2547 plist = plist->next;
2548 }
2549
2550 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
2551
2552 if (!blnMatch)
2553 sprintf(dev_name_str, "\n\nN = 0000");
2554
2555 if (copy_to_user(wrqu->data.pointer, dev_name_str, 5 + ((dev_len > 17) ? dev_len : 17)))
2556 return -EFAULT;
2557 return 0;
2558 }
2559
rtw_p2p_get_invitation_procedure(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2560 static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
2561 struct iw_request_info *info,
2562 union iwreq_data *wrqu, char *extra)
2563 {
2564 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2565 u8 peerMAC[ETH_ALEN] = {0x00};
2566 int jj, kk;
2567 u8 peerMACStr[17] = {0x00};
2568 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2569 struct list_head *plist, *phead;
2570 struct __queue *queue = &pmlmepriv->scanned_queue;
2571 struct wlan_network *pnetwork = NULL;
2572 u8 blnMatch = 0;
2573 u8 *p2pie;
2574 uint p2pielen = 0, attr_contentlen = 0;
2575 u8 attr_content[2] = {0x00};
2576
2577 u8 inv_proc_str[17 + 8] = {0x00};
2578 /* +8 is for the str "InvProc =", we have to clear it at wrqu->data.pointer */
2579
2580 /* Commented by Ouden 20121226 */
2581 /* The application wants to know P2P initiation procedure is supported or not. */
2582 /* Format: iwpriv wlanx p2p_get2 InvProc = 00:E0:4C:00:00:05 */
2583
2584 if (copy_from_user(peerMACStr, wrqu->data.pointer + 8, 17))
2585 return -EFAULT;
2586
2587 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
2588 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
2589
2590 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
2591
2592 phead = get_list_head(queue);
2593 plist = phead->next;
2594
2595 while (phead != plist) {
2596 pnetwork = container_of(plist, struct wlan_network, list);
2597 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
2598 /* Commented by Albert 20121226 */
2599 /* Match the device address located in the P2P IE */
2600 /* This is for the case that the P2P device address is not the same as the P2P interface address. */
2601
2602 p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
2603 if (p2pie) {
2604 while (p2pie) {
2605 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_CAPABILITY, attr_content, &attr_contentlen)) {
2606 /* Handle the P2P capability attribute */
2607 blnMatch = 1;
2608 break;
2609 }
2610
2611 /* Get the next P2P IE */
2612 p2pie = rtw_get_p2p_ie(p2pie + p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
2613 }
2614 }
2615 }
2616 plist = plist->next;
2617 }
2618
2619 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
2620
2621 if (!blnMatch) {
2622 sprintf(inv_proc_str, "\nIP =-1");
2623 } else {
2624 if (attr_content[0] & 0x20)
2625 sprintf(inv_proc_str, "\nIP = 1");
2626 else
2627 sprintf(inv_proc_str, "\nIP = 0");
2628 }
2629 if (copy_to_user(wrqu->data.pointer, inv_proc_str, 8 + 17))
2630 return -EFAULT;
2631 return 0;
2632 }
2633
rtw_p2p_connect(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2634 static int rtw_p2p_connect(struct net_device *dev,
2635 struct iw_request_info *info,
2636 union iwreq_data *wrqu, char *extra)
2637 {
2638 int ret = 0;
2639 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2640 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2641 u8 peerMAC[ETH_ALEN] = {0x00};
2642 int jj, kk;
2643 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2644 struct list_head *plist, *phead;
2645 struct __queue *queue = &pmlmepriv->scanned_queue;
2646 struct wlan_network *pnetwork = NULL;
2647 u32 peer_channel = 0;
2648
2649 /* Commented by Albert 20110304 */
2650 /* The input data contains two informations. */
2651 /* 1. First information is the MAC address which wants to formate with */
2652 /* 2. Second information is the WPS PINCode or "pbc" string for push button method */
2653 /* Format: 00:E0:4C:00:00:05 */
2654 /* Format: 00:E0:4C:00:00:05 */
2655
2656 if (pwdinfo->p2p_state == P2P_STATE_NONE)
2657 return ret;
2658
2659 if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO)
2660 return -1;
2661
2662 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
2663 peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
2664
2665 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
2666
2667 phead = get_list_head(queue);
2668 plist = phead->next;
2669
2670 while (phead != plist) {
2671 pnetwork = container_of(plist, struct wlan_network, list);
2672 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
2673 peer_channel = pnetwork->network.Configuration.DSConfig;
2674 break;
2675 }
2676
2677 plist = plist->next;
2678 }
2679
2680 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
2681
2682 if (peer_channel) {
2683 memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
2684 memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
2685
2686 pwdinfo->nego_req_info.peer_channel_num[0] = peer_channel;
2687 memcpy(pwdinfo->nego_req_info.peerDevAddr, pnetwork->network.MacAddress, ETH_ALEN);
2688 pwdinfo->nego_req_info.benable = true;
2689
2690 _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
2691 if (rtw_p2p_state(pwdinfo) != P2P_STATE_GONEGO_OK) {
2692 /* Restore to the listen state if the current p2p state is not nego OK */
2693 rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
2694 }
2695
2696 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
2697 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
2698
2699 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
2700 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT);
2701 } else {
2702 ret = -1;
2703 }
2704 return ret;
2705 }
2706
rtw_p2p_invite_req(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2707 static void rtw_p2p_invite_req(struct net_device *dev,
2708 struct iw_request_info *info,
2709 union iwreq_data *wrqu, char *extra)
2710 {
2711 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2712 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2713 int jj, kk;
2714 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2715 struct list_head *plist, *phead;
2716 struct __queue *queue = &pmlmepriv->scanned_queue;
2717 struct wlan_network *pnetwork = NULL;
2718 uint peer_channel = 0;
2719 u8 attr_content[50] = {0x00};
2720 u8 *p2pie;
2721 uint p2pielen = 0, attr_contentlen = 0;
2722 struct tx_invite_req_info *pinvite_req_info = &pwdinfo->invitereq_info;
2723
2724 /* The input data contains two informations. */
2725 /* 1. First information is the P2P device address which you want to send to. */
2726 /* 2. Second information is the group id which combines with GO's mac address, space and GO's ssid. */
2727 /* Command line sample: iwpriv wlan0 p2p_set invite ="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */
2728 /* Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy */
2729
2730 if (wrqu->data.length <= 37)
2731 return;
2732
2733 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
2734 return;
2735 } else {
2736 /* Reset the content of struct tx_invite_req_info */
2737 pinvite_req_info->benable = false;
2738 memset(pinvite_req_info->go_bssid, 0x00, ETH_ALEN);
2739 memset(pinvite_req_info->go_ssid, 0x00, WLAN_SSID_MAXLEN);
2740 pinvite_req_info->ssidlen = 0x00;
2741 pinvite_req_info->operating_ch = pwdinfo->operating_channel;
2742 memset(pinvite_req_info->peer_macaddr, 0x00, ETH_ALEN);
2743 pinvite_req_info->token = 3;
2744 }
2745
2746 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
2747 pinvite_req_info->peer_macaddr[jj] = key_2char2num(extra[kk], extra[kk + 1]);
2748
2749 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
2750
2751 phead = get_list_head(queue);
2752 plist = phead->next;
2753
2754 while (phead != plist) {
2755 pnetwork = container_of(plist, struct wlan_network, list);
2756
2757 /* Commented by Albert 2011/05/18 */
2758 /* Match the device address located in the P2P IE */
2759 /* This is for the case that the P2P device address is not the same as the P2P interface address. */
2760
2761 p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
2762 if (p2pie) {
2763 /* The P2P Device ID attribute is included in the Beacon frame. */
2764 /* The P2P Device Info attribute is included in the probe response frame. */
2765
2766 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
2767 /* Handle the P2P Device ID attribute of Beacon first */
2768 if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
2769 peer_channel = pnetwork->network.Configuration.DSConfig;
2770 break;
2771 }
2772 } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
2773 /* Handle the P2P Device Info attribute of probe response */
2774 if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
2775 peer_channel = pnetwork->network.Configuration.DSConfig;
2776 break;
2777 }
2778 }
2779 }
2780 plist = plist->next;
2781 }
2782
2783 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
2784
2785 if (peer_channel) {
2786 /* Store the GO's bssid */
2787 for (jj = 0, kk = 18; jj < ETH_ALEN; jj++, kk += 3)
2788 pinvite_req_info->go_bssid[jj] = key_2char2num(extra[kk], extra[kk + 1]);
2789
2790 /* Store the GO's ssid */
2791 pinvite_req_info->ssidlen = wrqu->data.length - 36;
2792 memcpy(pinvite_req_info->go_ssid, &extra[36], (u32)pinvite_req_info->ssidlen);
2793 pinvite_req_info->benable = true;
2794 pinvite_req_info->peer_ch = peer_channel;
2795
2796 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
2797 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INVITE_REQ);
2798
2799 set_channel_bwmode(padapter, peer_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
2800
2801 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
2802
2803 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT);
2804 }
2805 }
2806
rtw_p2p_set_persistent(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2807 static void rtw_p2p_set_persistent(struct net_device *dev,
2808 struct iw_request_info *info,
2809 union iwreq_data *wrqu, char *extra)
2810 {
2811 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2812 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2813
2814 /* The input data is 0 or 1 */
2815 /* 0: disable persistent group functionality */
2816 /* 1: enable persistent group founctionality */
2817
2818 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
2819 return;
2820 } else {
2821 if (extra[0] == '0') /* Disable the persistent group function. */
2822 pwdinfo->persistent_supported = false;
2823 else if (extra[0] == '1') /* Enable the persistent group function. */
2824 pwdinfo->persistent_supported = true;
2825 else
2826 pwdinfo->persistent_supported = false;
2827 }
2828 pr_info("[%s] persistent_supported = %d\n", __func__, pwdinfo->persistent_supported);
2829 }
2830
rtw_p2p_prov_disc(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2831 static void rtw_p2p_prov_disc(struct net_device *dev,
2832 struct iw_request_info *info,
2833 union iwreq_data *wrqu, char *extra)
2834 {
2835 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2836 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2837 u8 peerMAC[ETH_ALEN] = {0x00};
2838 int jj, kk;
2839 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2840 struct list_head *plist, *phead;
2841 struct __queue *queue = &pmlmepriv->scanned_queue;
2842 struct wlan_network *pnetwork = NULL;
2843 uint peer_channel = 0;
2844 u8 attr_content[100] = {0x00};
2845 u8 *p2pie;
2846 uint p2pielen = 0, attr_contentlen = 0;
2847
2848 /* The input data contains two informations. */
2849 /* 1. First information is the MAC address which wants to issue the provisioning discovery request frame. */
2850 /* 2. Second information is the WPS configuration method which wants to discovery */
2851 /* Format: 00:E0:4C:00:00:05_display */
2852 /* Format: 00:E0:4C:00:00:05_keypad */
2853 /* Format: 00:E0:4C:00:00:05_pbc */
2854 /* Format: 00:E0:4C:00:00:05_label */
2855
2856 if (pwdinfo->p2p_state == P2P_STATE_NONE) {
2857 return;
2858 } else {
2859 /* Reset the content of struct tx_provdisc_req_info excluded the wps_config_method_request. */
2860 memset(pwdinfo->tx_prov_disc_info.peerDevAddr, 0x00, ETH_ALEN);
2861 memset(pwdinfo->tx_prov_disc_info.peerIFAddr, 0x00, ETH_ALEN);
2862 memset(&pwdinfo->tx_prov_disc_info.ssid, 0x00, sizeof(struct ndis_802_11_ssid));
2863 pwdinfo->tx_prov_disc_info.peer_channel_num[0] = 0;
2864 pwdinfo->tx_prov_disc_info.peer_channel_num[1] = 0;
2865 pwdinfo->tx_prov_disc_info.benable = false;
2866 }
2867
2868 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
2869 peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
2870
2871 if (!memcmp(&extra[18], "display", 7))
2872 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA;
2873 else if (!memcmp(&extra[18], "keypad", 7))
2874 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD;
2875 else if (!memcmp(&extra[18], "pbc", 3))
2876 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
2877 else if (!memcmp(&extra[18], "label", 5))
2878 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL;
2879 else
2880 return;
2881
2882 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
2883
2884 phead = get_list_head(queue);
2885 plist = phead->next;
2886
2887 while (phead != plist) {
2888 if (peer_channel != 0)
2889 break;
2890
2891 pnetwork = container_of(plist, struct wlan_network, list);
2892
2893 /* Commented by Albert 2011/05/18 */
2894 /* Match the device address located in the P2P IE */
2895 /* This is for the case that the P2P device address is not the same as the P2P interface address. */
2896
2897 p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
2898 if (p2pie) {
2899 while (p2pie) {
2900 /* The P2P Device ID attribute is included in the Beacon frame. */
2901 /* The P2P Device Info attribute is included in the probe response frame. */
2902
2903 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
2904 /* Handle the P2P Device ID attribute of Beacon first */
2905 if (!memcmp(attr_content, peerMAC, ETH_ALEN)) {
2906 peer_channel = pnetwork->network.Configuration.DSConfig;
2907 break;
2908 }
2909 } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
2910 /* Handle the P2P Device Info attribute of probe response */
2911 if (!memcmp(attr_content, peerMAC, ETH_ALEN)) {
2912 peer_channel = pnetwork->network.Configuration.DSConfig;
2913 break;
2914 }
2915 }
2916
2917 /* Get the next P2P IE */
2918 p2pie = rtw_get_p2p_ie(p2pie + p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
2919 }
2920 }
2921
2922 plist = plist->next;
2923 }
2924
2925 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
2926
2927 if (peer_channel) {
2928 memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, pnetwork->network.MacAddress, ETH_ALEN);
2929 memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, peerMAC, ETH_ALEN);
2930 pwdinfo->tx_prov_disc_info.peer_channel_num[0] = (u16)peer_channel;
2931 pwdinfo->tx_prov_disc_info.benable = true;
2932 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
2933 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ);
2934
2935 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
2936 memcpy(&pwdinfo->tx_prov_disc_info.ssid, &pnetwork->network.Ssid, sizeof(struct ndis_802_11_ssid));
2937 } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2938 memcpy(pwdinfo->tx_prov_disc_info.ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
2939 pwdinfo->tx_prov_disc_info.ssid.SsidLength = P2P_WILDCARD_SSID_LEN;
2940 }
2941
2942 set_channel_bwmode(padapter, peer_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
2943
2944 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
2945
2946 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
2947 }
2948 }
2949
2950 /* This function is used to inform the driver the user had specified the pin code value or pbc */
2951 /* to application. */
2952
rtw_p2p_got_wpsinfo(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2953 static void rtw_p2p_got_wpsinfo(struct net_device *dev,
2954 struct iw_request_info *info,
2955 union iwreq_data *wrqu, char *extra)
2956 {
2957 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2958 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2959
2960 /* Added by Albert 20110328 */
2961 /* if the input data is P2P_NO_WPSINFO -> reset the wpsinfo */
2962 /* if the input data is P2P_GOT_WPSINFO_PEER_DISPLAY_PIN -> the utility just input the PIN code got from the peer P2P device. */
2963 /* if the input data is P2P_GOT_WPSINFO_SELF_DISPLAY_PIN -> the utility just got the PIN code from itself. */
2964 /* if the input data is P2P_GOT_WPSINFO_PBC -> the utility just determine to use the PBC */
2965
2966 if (*extra == '0')
2967 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
2968 else if (*extra == '1')
2969 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PEER_DISPLAY_PIN;
2970 else if (*extra == '2')
2971 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_SELF_DISPLAY_PIN;
2972 else if (*extra == '3')
2973 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PBC;
2974 else
2975 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
2976 }
2977
rtw_p2p_set(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2978 static int rtw_p2p_set(struct net_device *dev,
2979 struct iw_request_info *info,
2980 union iwreq_data *wrqu, char *extra)
2981 {
2982 int ret = 0;
2983
2984 if (!memcmp(extra, "enable =", 7)) {
2985 rtw_wext_p2p_enable(dev, info, wrqu, &extra[7]);
2986 } else if (!memcmp(extra, "setDN =", 6)) {
2987 wrqu->data.length -= 6;
2988 rtw_p2p_setDN(dev, info, wrqu, &extra[6]);
2989 } else if (!memcmp(extra, "profilefound =", 13)) {
2990 wrqu->data.length -= 13;
2991 rtw_p2p_profilefound(dev, info, wrqu, &extra[13]);
2992 } else if (!memcmp(extra, "prov_disc =", 10)) {
2993 wrqu->data.length -= 10;
2994 rtw_p2p_prov_disc(dev, info, wrqu, &extra[10]);
2995 } else if (!memcmp(extra, "nego =", 5)) {
2996 wrqu->data.length -= 5;
2997 rtw_p2p_connect(dev, info, wrqu, &extra[5]);
2998 } else if (!memcmp(extra, "intent =", 7)) {
2999 /* Commented by Albert 2011/03/23 */
3000 /* The wrqu->data.length will include the null character */
3001 /* So, we will decrease 7 + 1 */
3002 wrqu->data.length -= 8;
3003 rtw_p2p_set_intent(dev, info, wrqu, &extra[7]);
3004 } else if (!memcmp(extra, "ssid =", 5)) {
3005 wrqu->data.length -= 5;
3006 rtw_p2p_set_go_nego_ssid(dev, info, wrqu, &extra[5]);
3007 } else if (!memcmp(extra, "got_wpsinfo =", 12)) {
3008 wrqu->data.length -= 12;
3009 rtw_p2p_got_wpsinfo(dev, info, wrqu, &extra[12]);
3010 } else if (!memcmp(extra, "listen_ch =", 10)) {
3011 /* Commented by Albert 2011/05/24 */
3012 /* The wrqu->data.length will include the null character */
3013 /* So, we will decrease (10 + 1) */
3014 wrqu->data.length -= 11;
3015 rtw_p2p_set_listen_ch(dev, info, wrqu, &extra[10]);
3016 } else if (!memcmp(extra, "op_ch =", 6)) {
3017 /* Commented by Albert 2011/05/24 */
3018 /* The wrqu->data.length will include the null character */
3019 /* So, we will decrease (6 + 1) */
3020 wrqu->data.length -= 7;
3021 rtw_p2p_set_op_ch(dev, info, wrqu, &extra[6]);
3022 } else if (!memcmp(extra, "invite =", 7)) {
3023 wrqu->data.length -= 8;
3024 rtw_p2p_invite_req(dev, info, wrqu, &extra[7]);
3025 } else if (!memcmp(extra, "persistent =", 11)) {
3026 wrqu->data.length -= 11;
3027 rtw_p2p_set_persistent(dev, info, wrqu, &extra[11]);
3028 }
3029
3030 return ret;
3031 }
3032
rtw_p2p_get2(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)3033 static int rtw_p2p_get2(struct net_device *dev,
3034 struct iw_request_info *info,
3035 union iwreq_data *wrqu, char *extra)
3036 {
3037 int ret = 0;
3038
3039 if (!memcmp(extra, "wpsCM =", 6)) {
3040 wrqu->data.length -= 6;
3041 ret = rtw_p2p_get_wps_configmethod(dev, info, wrqu, &extra[6]);
3042 } else if (!memcmp(extra, "devN =", 5)) {
3043 wrqu->data.length -= 5;
3044 ret = rtw_p2p_get_device_name(dev, info, wrqu, &extra[5]);
3045 } else if (!memcmp(extra, "dev_type =", 9)) {
3046 wrqu->data.length -= 9;
3047 ret = rtw_p2p_get_device_type(dev, info, wrqu, &extra[9]);
3048 } else if (!memcmp(extra, "go_devadd =", 10)) {
3049 wrqu->data.length -= 10;
3050 ret = rtw_p2p_get_go_device_address(dev, info, wrqu, &extra[10]);
3051 } else if (!memcmp(extra, "InvProc =", 8)) {
3052 wrqu->data.length -= 8;
3053 ret = rtw_p2p_get_invitation_procedure(dev, info, wrqu, &extra[8]);
3054 }
3055
3056 return ret;
3057 }
3058
rtw_rereg_nd_name(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)3059 static int rtw_rereg_nd_name(struct net_device *dev,
3060 struct iw_request_info *info,
3061 union iwreq_data *wrqu, char *extra)
3062 {
3063 int ret = 0;
3064 struct adapter *padapter = rtw_netdev_priv(dev);
3065 struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv;
3066 char new_ifname[IFNAMSIZ];
3067
3068 if (rereg_priv->old_ifname[0] == 0) {
3069 char *reg_ifname;
3070 reg_ifname = padapter->registrypriv.if2name;
3071
3072 strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ);
3073 rereg_priv->old_ifname[IFNAMSIZ - 1] = 0;
3074 }
3075
3076 if (wrqu->data.length > IFNAMSIZ)
3077 return -EFAULT;
3078
3079 if (copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ))
3080 return -EFAULT;
3081
3082 if (0 == strcmp(rereg_priv->old_ifname, new_ifname))
3083 return ret;
3084
3085 ret = rtw_change_ifname(padapter, new_ifname);
3086 if (0 != ret)
3087 goto exit;
3088
3089 if (!memcmp(rereg_priv->old_ifname, "disable%d", 9)) {
3090 padapter->ledpriv.bRegUseLed = rereg_priv->old_bRegUseLed;
3091 rtl8188eu_InitSwLeds(padapter);
3092 rtw_ips_mode_req(&padapter->pwrctrlpriv, rereg_priv->old_ips_mode);
3093 }
3094
3095 strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
3096 rereg_priv->old_ifname[IFNAMSIZ - 1] = 0;
3097
3098 if (!memcmp(new_ifname, "disable%d", 9)) {
3099 /* free network queue for Android's timming issue */
3100 rtw_free_network_queue(padapter, true);
3101
3102 /* close led */
3103 rtw_led_control(padapter, LED_CTL_POWER_OFF);
3104 rereg_priv->old_bRegUseLed = padapter->ledpriv.bRegUseLed;
3105 padapter->ledpriv.bRegUseLed = false;
3106 rtl8188eu_DeInitSwLeds(padapter);
3107
3108 /* the interface is being "disabled", we can do deeper IPS */
3109 rereg_priv->old_ips_mode = rtw_get_ips_mode_req(&padapter->pwrctrlpriv);
3110 rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL);
3111 }
3112 exit:
3113 return ret;
3114 }
3115
mac_reg_dump(struct adapter * padapter)3116 static void mac_reg_dump(struct adapter *padapter)
3117 {
3118 int i, j = 1;
3119 u32 reg;
3120 int res;
3121
3122 pr_info("\n ======= MAC REG =======\n");
3123 for (i = 0x0; i < 0x300; i += 4) {
3124 if (j % 4 == 1)
3125 pr_info("0x%02x", i);
3126
3127 res = rtw_read32(padapter, i, ®);
3128 if (!res)
3129 pr_info(" 0x%08x ", reg);
3130
3131 if ((j++) % 4 == 0)
3132 pr_info("\n");
3133 }
3134 for (i = 0x400; i < 0x800; i += 4) {
3135 if (j % 4 == 1)
3136 pr_info("0x%02x", i);
3137
3138 res = rtw_read32(padapter, i, ®);
3139 if (!res)
3140 pr_info(" 0x%08x ", reg);
3141
3142 if ((j++) % 4 == 0)
3143 pr_info("\n");
3144 }
3145 }
3146
bb_reg_dump(struct adapter * padapter)3147 static void bb_reg_dump(struct adapter *padapter)
3148 {
3149 int i, j = 1, res;
3150 u32 reg;
3151
3152 pr_info("\n ======= BB REG =======\n");
3153 for (i = 0x800; i < 0x1000; i += 4) {
3154 if (j % 4 == 1)
3155 pr_info("0x%02x", i);
3156
3157 res = rtw_read32(padapter, i, ®);
3158 if (!res)
3159 pr_info(" 0x%08x ", reg);
3160
3161 if ((j++) % 4 == 0)
3162 pr_info("\n");
3163 }
3164 }
3165
rf_reg_dump(struct adapter * padapter)3166 static void rf_reg_dump(struct adapter *padapter)
3167 {
3168 int i, j = 1;
3169 u32 value;
3170
3171 pr_info("\n ======= RF REG =======\n");
3172 pr_info("\nRF_Path(%x)\n", RF_PATH_A);
3173 for (i = 0; i < 0x100; i++) {
3174 value = rtl8188e_PHY_QueryRFReg(padapter, i, 0xffffffff);
3175 if (j % 4 == 1)
3176 pr_info("0x%02x ", i);
3177 pr_info(" 0x%08x ", value);
3178 if ((j++) % 4 == 0)
3179 pr_info("\n");
3180 }
3181 }
3182
rtw_set_dynamic_functions(struct adapter * adapter,u8 dm_func)3183 static void rtw_set_dynamic_functions(struct adapter *adapter, u8 dm_func)
3184 {
3185 struct hal_data_8188e *haldata = &adapter->haldata;
3186 struct odm_dm_struct *odmpriv = &haldata->odmpriv;
3187 int res;
3188
3189 switch (dm_func) {
3190 case 0:
3191 /* disable all dynamic func */
3192 odmpriv->SupportAbility = DYNAMIC_FUNC_DISABLE;
3193 break;
3194 case 1:
3195 /* disable DIG */
3196 odmpriv->SupportAbility &= (~DYNAMIC_BB_DIG);
3197 break;
3198 case 6:
3199 /* turn on all dynamic func */
3200 if (!(odmpriv->SupportAbility & DYNAMIC_BB_DIG)) {
3201 struct rtw_dig *digtable = &odmpriv->DM_DigTable;
3202
3203 res = rtw_read8(adapter, 0xc50, &digtable->CurIGValue);
3204 (void)res;
3205 /* FIXME: return an error to caller */
3206 }
3207 odmpriv->SupportAbility = DYNAMIC_ALL_FUNC_ENABLE;
3208 break;
3209 default:
3210 break;
3211 }
3212 }
3213
rtw_set_dm_func_flag(struct adapter * adapter,u32 odm_flag)3214 static void rtw_set_dm_func_flag(struct adapter *adapter, u32 odm_flag)
3215 {
3216 struct hal_data_8188e *haldata = &adapter->haldata;
3217 struct odm_dm_struct *odmpriv = &haldata->odmpriv;
3218
3219 odmpriv->SupportAbility = odm_flag;
3220 }
3221
rtw_dbg_port(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)3222 static int rtw_dbg_port(struct net_device *dev,
3223 struct iw_request_info *info,
3224 union iwreq_data *wrqu, char *extra)
3225 {
3226 int ret = 0;
3227 u8 major_cmd, minor_cmd;
3228 u16 arg;
3229 s32 extra_arg;
3230 u32 *pdata, val32;
3231 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3232 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3233 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3234 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3235 struct wlan_network *cur_network = &pmlmepriv->cur_network;
3236 struct sta_priv *pstapriv = &padapter->stapriv;
3237
3238 pdata = (u32 *)&wrqu->data;
3239
3240 val32 = *pdata;
3241 arg = (u16)(val32 & 0x0000ffff);
3242 major_cmd = (u8)(val32 >> 24);
3243 minor_cmd = (u8)((val32 >> 16) & 0x00ff);
3244
3245 extra_arg = *(pdata + 1);
3246
3247 switch (major_cmd) {
3248 case 0x70:/* read_reg */
3249 switch (minor_cmd) {
3250 case 1:
3251 break;
3252 case 2:
3253 break;
3254 case 4:
3255 break;
3256 }
3257 break;
3258 case 0x71:/* write_reg */
3259 switch (minor_cmd) {
3260 case 1:
3261 rtw_write8(padapter, arg, extra_arg);
3262 break;
3263 case 2:
3264 rtw_write16(padapter, arg, extra_arg);
3265 break;
3266 case 4:
3267 rtw_write32(padapter, arg, extra_arg);
3268 break;
3269 }
3270 break;
3271 case 0x72:/* read_bb */
3272 break;
3273 case 0x73:/* write_bb */
3274 rtl8188e_PHY_SetBBReg(padapter, arg, 0xffffffff, extra_arg);
3275 break;
3276 case 0x74:/* read_rf */
3277 if (minor_cmd != RF_PATH_A) {
3278 ret = -EINVAL;
3279 break;
3280 }
3281 break;
3282 case 0x75:/* write_rf */
3283 if (minor_cmd != RF_PATH_A) {
3284 ret = -EINVAL;
3285 break;
3286 }
3287 rtl8188e_PHY_SetRFReg(padapter, arg, 0xffffffff, extra_arg);
3288 break;
3289
3290 case 0x76:
3291 switch (minor_cmd) {
3292 case 0x00: /* normal mode, */
3293 padapter->recvpriv.is_signal_dbg = 0;
3294 break;
3295 case 0x01: /* dbg mode */
3296 padapter->recvpriv.is_signal_dbg = 1;
3297 extra_arg = extra_arg > 100 ? 100 : extra_arg;
3298 extra_arg = extra_arg < 0 ? 0 : extra_arg;
3299 padapter->recvpriv.signal_strength_dbg = extra_arg;
3300 break;
3301 }
3302 break;
3303 case 0x78: /* IOL test */
3304 switch (minor_cmd) {
3305 case 0x04: /* LLT table initialization test */
3306 {
3307 struct xmit_frame *xmit_frame;
3308
3309 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
3310 if (!xmit_frame) {
3311 ret = -ENOMEM;
3312 break;
3313 }
3314
3315 if (rtl8188e_IOL_exec_cmds_sync(padapter, xmit_frame, 500, 0) != _SUCCESS)
3316 ret = -EPERM;
3317 }
3318 break;
3319 case 0x05: /* blink LED test */
3320 {
3321 u16 reg = 0x4c;
3322 u32 blink_num = 50;
3323 u32 blink_delay_ms = 200;
3324 int i;
3325 struct xmit_frame *xmit_frame;
3326
3327 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
3328 if (!xmit_frame) {
3329 ret = -ENOMEM;
3330 break;
3331 }
3332
3333 for (i = 0; i < blink_num; i++) {
3334 rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00, 0xff);
3335 rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
3336 rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08, 0xff);
3337 rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
3338 }
3339 if (rtl8188e_IOL_exec_cmds_sync(padapter, xmit_frame, (blink_delay_ms * blink_num * 2) + 200, 0) != _SUCCESS)
3340 ret = -EPERM;
3341 }
3342 break;
3343
3344 case 0x06: /* continuous write byte test */
3345 {
3346 u16 reg = arg;
3347 u16 start_value = 0;
3348 u32 write_num = extra_arg;
3349 int i, res;
3350 struct xmit_frame *xmit_frame;
3351 u8 val8;
3352
3353 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
3354 if (!xmit_frame) {
3355 ret = -ENOMEM;
3356 break;
3357 }
3358
3359 for (i = 0; i < write_num; i++)
3360 rtw_IOL_append_WB_cmd(xmit_frame, reg, i + start_value, 0xFF);
3361 if (rtl8188e_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0) != _SUCCESS)
3362 ret = -EPERM;
3363
3364 /* FIXME: is this read necessary? */
3365 res = rtw_read8(padapter, reg, &val8);
3366 (void)res;
3367 }
3368 break;
3369
3370 case 0x07: /* continuous write word test */
3371 {
3372 u16 reg = arg;
3373 u16 start_value = 200;
3374 u32 write_num = extra_arg;
3375 u16 val16;
3376 int i, res;
3377 struct xmit_frame *xmit_frame;
3378
3379 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
3380 if (!xmit_frame) {
3381 ret = -ENOMEM;
3382 break;
3383 }
3384
3385 for (i = 0; i < write_num; i++)
3386 rtw_IOL_append_WW_cmd(xmit_frame, reg, i + start_value, 0xFFFF);
3387 if (rtl8188e_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0) != _SUCCESS)
3388 ret = -EPERM;
3389
3390 /* FIXME: is this read necessary? */
3391 res = rtw_read16(padapter, reg, &val16);
3392 (void)res;
3393 }
3394 break;
3395 case 0x08: /* continuous write dword test */
3396 {
3397 u16 reg = arg;
3398 u32 start_value = 0x110000c7;
3399 u32 write_num = extra_arg;
3400
3401 int i;
3402 struct xmit_frame *xmit_frame;
3403
3404 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
3405 if (!xmit_frame) {
3406 ret = -ENOMEM;
3407 break;
3408 }
3409
3410 for (i = 0; i < write_num; i++)
3411 rtw_IOL_append_WD_cmd(xmit_frame, reg, i + start_value, 0xFFFFFFFF);
3412 if (rtl8188e_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0) != _SUCCESS)
3413 ret = -EPERM;
3414
3415 /* FIXME: is this read necessary? */
3416 ret = rtw_read32(padapter, reg, &write_num);
3417 }
3418 break;
3419 }
3420 break;
3421 case 0x79:
3422 {
3423 /*
3424 * dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15
3425 * dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15
3426 */
3427 u8 value = extra_arg & 0x0f;
3428 u8 sign = minor_cmd;
3429 u16 write_value = 0;
3430
3431 if (sign)
3432 value = value | 0x10;
3433
3434 write_value = value | (value << 5);
3435 rtw_write16(padapter, 0x6d9, write_value);
3436 }
3437 break;
3438 case 0x7a:
3439 receive_disconnect(padapter, pmlmeinfo->network.MacAddress
3440 , WLAN_REASON_EXPIRATION_CHK);
3441 break;
3442 case 0x7F:
3443 switch (minor_cmd) {
3444 case 0x0:
3445 break;
3446 case 0x01:
3447 break;
3448 case 0x02:
3449 break;
3450 case 0x03:
3451 break;
3452 case 0x04:
3453 break;
3454 case 0x05:
3455 rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
3456 break;
3457 case 0x06:
3458 {
3459 u32 ODMFlag = (u32)(0x0f & arg);
3460 rtw_set_dm_func_flag(padapter, ODMFlag);
3461 }
3462 break;
3463 case 0x07:
3464 break;
3465 case 0x08:
3466 break;
3467 case 0x09:
3468 break;
3469 case 0x15:
3470 break;
3471 case 0x10:/* driver version display */
3472 break;
3473 case 0x11:
3474 padapter->bRxRSSIDisplay = extra_arg;
3475 break;
3476 case 0x12: /* set rx_stbc */
3477 {
3478 struct registry_priv *pregpriv = &padapter->registrypriv;
3479 /* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g */
3480 /* default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */
3481 if (extra_arg == 0 ||
3482 extra_arg == 1 ||
3483 extra_arg == 2 ||
3484 extra_arg == 3)
3485 pregpriv->rx_stbc = extra_arg;
3486 }
3487 break;
3488 case 0x13: /* set ampdu_enable */
3489 {
3490 struct registry_priv *pregpriv = &padapter->registrypriv;
3491 /* 0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec) */
3492 if (extra_arg >= 0 && extra_arg < 3)
3493 pregpriv->ampdu_enable = extra_arg;
3494 }
3495 break;
3496 case 0x14: /* get wifi_spec */
3497 break;
3498 case 0x23:
3499 padapter->bNotifyChannelChange = extra_arg;
3500 break;
3501 case 0x24:
3502 padapter->bShowGetP2PState = extra_arg;
3503 break;
3504 case 0xdd:/* registers dump, 0 for mac reg, 1 for bb reg, 2 for rf reg */
3505 if (extra_arg == 0)
3506 mac_reg_dump(padapter);
3507 else if (extra_arg == 1)
3508 bb_reg_dump(padapter);
3509 else if (extra_arg == 2)
3510 rf_reg_dump(padapter);
3511 break;
3512 case 0xee:/* turn on/off dynamic funcs */
3513 if (extra_arg != 0xf) {
3514 /* extra_arg = 0 - disable all dynamic func
3515 * extra_arg = 1 - disable DIG
3516 * extra_arg = 6 - turn on all dynamic func
3517 */
3518 rtw_set_dynamic_functions(padapter, extra_arg);
3519 }
3520 break;
3521 case 0xfd:
3522 rtw_write8(padapter, 0xc50, arg);
3523 rtw_write8(padapter, 0xc58, arg);
3524 break;
3525 case 0xfe:
3526 break;
3527 case 0xff:
3528 break;
3529 }
3530 break;
3531 default:
3532 break;
3533 }
3534 return ret;
3535 }
3536
rtw_wx_set_priv(struct net_device * dev,struct iw_request_info * info,union iwreq_data * awrq,char * extra)3537 static int rtw_wx_set_priv(struct net_device *dev,
3538 struct iw_request_info *info,
3539 union iwreq_data *awrq,
3540 char *extra)
3541 {
3542 int ret = 0;
3543 int len = 0;
3544 char *ext;
3545 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3546 struct iw_point *dwrq = (struct iw_point *)awrq;
3547
3548 if (dwrq->length == 0)
3549 return -EFAULT;
3550
3551 len = dwrq->length;
3552 ext = vmalloc(len);
3553 if (!ext)
3554 return -ENOMEM;
3555
3556 if (copy_from_user(ext, dwrq->pointer, len)) {
3557 vfree(ext);
3558 return -EFAULT;
3559 }
3560
3561 /* added for wps2.0 @20110524 */
3562 if (dwrq->flags == 0x8766 && len > 8) {
3563 u32 cp_sz;
3564 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3565 u8 *probereq_wpsie = ext;
3566 int probereq_wpsie_len = len;
3567 u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
3568
3569 if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
3570 (!memcmp(&probereq_wpsie[2], wps_oui, 4))) {
3571 cp_sz = probereq_wpsie_len > MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN : probereq_wpsie_len;
3572
3573 pmlmepriv->wps_probe_req_ie_len = 0;
3574 kfree(pmlmepriv->wps_probe_req_ie);
3575 pmlmepriv->wps_probe_req_ie = NULL;
3576
3577 pmlmepriv->wps_probe_req_ie = kmemdup(probereq_wpsie, cp_sz, GFP_KERNEL);
3578 if (!pmlmepriv->wps_probe_req_ie) {
3579 ret = -EINVAL;
3580 goto FREE_EXT;
3581 }
3582 pmlmepriv->wps_probe_req_ie_len = cp_sz;
3583 }
3584 goto FREE_EXT;
3585 }
3586
3587 if (len >= WEXT_CSCAN_HEADER_SIZE &&
3588 !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
3589 ret = rtw_wx_set_scan(dev, info, awrq, ext);
3590 goto FREE_EXT;
3591 }
3592
3593 FREE_EXT:
3594
3595 vfree(ext);
3596
3597 return ret;
3598 }
3599
rtw_pm_set(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)3600 static int rtw_pm_set(struct net_device *dev,
3601 struct iw_request_info *info,
3602 union iwreq_data *wrqu, char *extra)
3603 {
3604 int ret = 0;
3605 unsigned mode = 0;
3606 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3607
3608 if (!memcmp(extra, "lps =", 4)) {
3609 sscanf(extra + 4, "%u", &mode);
3610 ret = rtw_pm_set_lps(padapter, mode);
3611 } else if (!memcmp(extra, "ips =", 4)) {
3612 sscanf(extra + 4, "%u", &mode);
3613 ret = rtw_pm_set_ips(padapter, mode);
3614 } else {
3615 ret = -EINVAL;
3616 }
3617
3618 return ret;
3619 }
3620
3621 static iw_handler rtw_handlers[] = {
3622 IW_HANDLER(SIOCGIWNAME, rtw_wx_get_name),
3623 IW_HANDLER(SIOCGIWFREQ, rtw_wx_get_freq),
3624 IW_HANDLER(SIOCSIWMODE, rtw_wx_set_mode),
3625 IW_HANDLER(SIOCGIWMODE, rtw_wx_get_mode),
3626 IW_HANDLER(SIOCGIWSENS, rtw_wx_get_sens),
3627 IW_HANDLER(SIOCGIWRANGE, rtw_wx_get_range),
3628 IW_HANDLER(SIOCSIWPRIV, rtw_wx_set_priv),
3629 IW_HANDLER(SIOCSIWAP, rtw_wx_set_wap),
3630 IW_HANDLER(SIOCGIWAP, rtw_wx_get_wap),
3631 IW_HANDLER(SIOCSIWMLME, rtw_wx_set_mlme),
3632 IW_HANDLER(SIOCSIWSCAN, rtw_wx_set_scan),
3633 IW_HANDLER(SIOCGIWSCAN, rtw_wx_get_scan),
3634 IW_HANDLER(SIOCSIWESSID, rtw_wx_set_essid),
3635 IW_HANDLER(SIOCGIWESSID, rtw_wx_get_essid),
3636 IW_HANDLER(SIOCGIWNICKN, rtw_wx_get_nick),
3637 IW_HANDLER(SIOCSIWRATE, rtw_wx_set_rate),
3638 IW_HANDLER(SIOCGIWRATE, rtw_wx_get_rate),
3639 IW_HANDLER(SIOCSIWRTS, rtw_wx_set_rts),
3640 IW_HANDLER(SIOCGIWRTS, rtw_wx_get_rts),
3641 IW_HANDLER(SIOCSIWFRAG, rtw_wx_set_frag),
3642 IW_HANDLER(SIOCGIWFRAG, rtw_wx_get_frag),
3643 IW_HANDLER(SIOCGIWRETRY, rtw_wx_get_retry),
3644 IW_HANDLER(SIOCSIWENCODE, rtw_wx_set_enc),
3645 IW_HANDLER(SIOCGIWENCODE, rtw_wx_get_enc),
3646 IW_HANDLER(SIOCGIWPOWER, rtw_wx_get_power),
3647 IW_HANDLER(SIOCSIWGENIE, rtw_wx_set_gen_ie),
3648 IW_HANDLER(SIOCSIWAUTH, rtw_wx_set_auth),
3649 IW_HANDLER(SIOCSIWENCODEEXT, rtw_wx_set_enc_ext),
3650 IW_HANDLER(SIOCSIWPMKSA, rtw_wx_set_pmkid),
3651 };
3652
3653 static const struct iw_priv_args rtw_private_args[] = {
3654 {
3655 SIOCIWFIRSTPRIV + 0x0,
3656 IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write"
3657 },
3658 {
3659 SIOCIWFIRSTPRIV + 0x1,
3660 IW_PRIV_TYPE_CHAR | 0x7FF,
3661 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read"
3662 },
3663 {
3664 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
3665 },
3666 {
3667 SIOCIWFIRSTPRIV + 0x4,
3668 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
3669 },
3670 {
3671 SIOCIWFIRSTPRIV + 0x5,
3672 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid"
3673 },
3674 {
3675 SIOCIWFIRSTPRIV + 0x6,
3676 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
3677 },
3678 {
3679 SIOCIWFIRSTPRIV + 0xA,
3680 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan"
3681 },
3682
3683 {
3684 SIOCIWFIRSTPRIV + 0xB,
3685 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg"
3686 },
3687 {
3688 SIOCIWFIRSTPRIV + 0xC,
3689 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw"
3690 },
3691 {
3692 SIOCIWFIRSTPRIV + 0xD,
3693 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr"
3694 },
3695 {
3696 SIOCIWFIRSTPRIV + 0x10,
3697 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, 0, "p2p_set"
3698 },
3699 {
3700 SIOCIWFIRSTPRIV + 0x11,
3701 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN, "p2p_get"
3702 },
3703 {
3704 SIOCIWFIRSTPRIV + 0x12,
3705 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IFNAMSIZ, "p2p_get2"
3706 },
3707 {
3708 SIOCIWFIRSTPRIV + 0x16,
3709 IW_PRIV_TYPE_CHAR | 64, 0, "pm_set"
3710 },
3711
3712 {SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ, 0, "rereg_nd_name"},
3713 };
3714
3715 static iw_handler rtw_private_handler[] = {
3716 NULL, /* 0x00 */
3717 NULL, /* 0x01 */
3718 NULL, /* 0x02 */
3719 NULL, /* 0x03 */
3720 /* for MM DTV platform */
3721 rtw_get_ap_info, /* 0x04 */
3722
3723 rtw_set_pid, /* 0x05 */
3724 rtw_wps_start, /* 0x06 */
3725
3726 NULL, /* 0x07 */
3727 NULL, /* 0x08 */
3728 NULL, /* 0x09 */
3729
3730 /* Set Channel depend on the country code */
3731 rtw_wx_set_channel_plan, /* 0x0A */
3732
3733 rtw_dbg_port, /* 0x0B */
3734 rtw_wx_write_rf, /* 0x0C */
3735 rtw_wx_read_rf, /* 0x0D */
3736 NULL, /* 0x0E */
3737 NULL, /* 0x0F */
3738
3739 rtw_p2p_set, /* 0x10 */
3740 NULL, /* 0x11 */
3741 rtw_p2p_get2, /* 0x12 */
3742
3743 NULL, /* 0x13 */
3744 NULL, /* 0x14 */
3745 NULL, /* 0x15 */
3746
3747 rtw_pm_set, /* 0x16 */
3748 NULL, /* 0x17 */
3749 rtw_rereg_nd_name, /* 0x18 */
3750 };
3751
rtw_get_wireless_stats(struct net_device * dev)3752 static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
3753 {
3754 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3755 struct iw_statistics *piwstats = &padapter->iwstats;
3756 int tmp_noise = 0;
3757 int tmp;
3758
3759 if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
3760 piwstats->qual.qual = 0;
3761 piwstats->qual.level = 0;
3762 piwstats->qual.noise = 0;
3763 } else {
3764 tmp_noise = padapter->recvpriv.noise;
3765
3766 piwstats->qual.level = padapter->signal_strength;
3767 tmp = 219 + 3 * padapter->signal_strength;
3768 tmp = min(100, tmp);
3769 tmp = max(0, tmp);
3770 piwstats->qual.qual = tmp;
3771 piwstats->qual.noise = tmp_noise;
3772 }
3773 piwstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
3774 return &padapter->iwstats;
3775 }
3776
3777 struct iw_handler_def rtw_handlers_def = {
3778 .standard = rtw_handlers,
3779 .num_standard = ARRAY_SIZE(rtw_handlers),
3780 .private = rtw_private_handler,
3781 .private_args = (struct iw_priv_args *)rtw_private_args,
3782 .num_private = ARRAY_SIZE(rtw_private_handler),
3783 .num_private_args = ARRAY_SIZE(rtw_private_args),
3784 .get_wireless_stats = rtw_get_wireless_stats,
3785 };
3786