1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2019 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15 #define _IOCTL_LINUX_C_
16
17 #include <drv_types.h>
18 #include <rtw_mp.h>
19 #include "../../hal/phydm/phydm_precomp.h"
20 #ifdef RTW_HALMAC
21 #include "../../hal/hal_halmac.h"
22 #endif
23
24 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27))
25 #define iwe_stream_add_event(a, b, c, d, e) iwe_stream_add_event(b, c, d, e)
26 #define iwe_stream_add_point(a, b, c, d, e) iwe_stream_add_point(b, c, d, e)
27 #endif
28
29 #ifdef CONFIG_80211N_HT
30 extern int rtw_ht_enable;
31 #endif
32
33
34 #define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV+30)
35
36 #define SCAN_ITEM_SIZE 768
37 #define MAX_CUSTOM_LEN 64
38 #define RATE_COUNT 4
39 #define MAX_SCAN_BUFFER_LEN 65535
40
41 #ifdef CONFIG_GLOBAL_UI_PID
42 extern int ui_pid[3];
43 #endif
44
45 /* combo scan */
46 #define WEXT_CSCAN_AMOUNT 9
47 #define WEXT_CSCAN_BUF_LEN 360
48 #define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00"
49 #define WEXT_CSCAN_HEADER_SIZE 12
50 #define WEXT_CSCAN_SSID_SECTION 'S'
51 #define WEXT_CSCAN_CHANNEL_SECTION 'C'
52 #define WEXT_CSCAN_NPROBE_SECTION 'N'
53 #define WEXT_CSCAN_ACTV_DWELL_SECTION 'A'
54 #define WEXT_CSCAN_PASV_DWELL_SECTION 'P'
55 #define WEXT_CSCAN_HOME_DWELL_SECTION 'H'
56 #define WEXT_CSCAN_TYPE_SECTION 'T'
57
58
59 extern u8 key_2char2num(u8 hch, u8 lch);
60 extern u8 str_2char2num(u8 hch, u8 lch);
61 extern void macstr2num(u8 *dst, u8 *src);
62 extern u8 convert_ip_addr(u8 hch, u8 mch, u8 lch);
63
64 u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000,
65 6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000};
66
67 /**
68 * hwaddr_aton - Convert ASCII string to MAC address
69 * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
70 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
71 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
72 */
hwaddr_aton_i(const char * txt,u8 * addr)73 static int hwaddr_aton_i(const char *txt, u8 *addr)
74 {
75 int i;
76
77 for (i = 0; i < 6; i++) {
78 int a, b;
79
80 a = hex2num_i(*txt++);
81 if (a < 0)
82 return -1;
83 b = hex2num_i(*txt++);
84 if (b < 0)
85 return -1;
86 *addr++ = (a << 4) | b;
87 if (i < 5 && *txt++ != ':')
88 return -1;
89 }
90
91 return 0;
92 }
93 #ifdef CONFIG_RTW_ANDROID
indicate_wx_custom_event(_adapter * padapter,char * msg)94 static void indicate_wx_custom_event(_adapter *padapter, char *msg)
95 {
96 u8 *buff;
97 union iwreq_data wrqu;
98
99 if (strlen(msg) > IW_CUSTOM_MAX) {
100 RTW_INFO("%s strlen(msg):%zu > IW_CUSTOM_MAX:%u\n", __FUNCTION__ , strlen(msg), IW_CUSTOM_MAX);
101 return;
102 }
103
104 buff = rtw_zmalloc(IW_CUSTOM_MAX + 1);
105 if (!buff)
106 return;
107
108 _rtw_memcpy(buff, msg, strlen(msg));
109
110 _rtw_memset(&wrqu, 0, sizeof(wrqu));
111 wrqu.data.length = strlen(msg);
112
113 RTW_INFO("%s %s\n", __FUNCTION__, buff);
114 #ifndef CONFIG_IOCTL_CFG80211
115 wireless_send_event(padapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
116 #endif
117
118 rtw_mfree(buff, IW_CUSTOM_MAX + 1);
119
120 }
121 #endif
122
123 #if 0
124 static void request_wps_pbc_event(_adapter *padapter)
125 {
126 u8 *buff, *p;
127 union iwreq_data wrqu;
128
129
130 buff = rtw_malloc(IW_CUSTOM_MAX);
131 if (!buff)
132 return;
133
134 _rtw_memset(buff, 0, IW_CUSTOM_MAX);
135
136 p = buff;
137
138 p += sprintf(p, "WPS_PBC_START.request=TRUE");
139
140 _rtw_memset(&wrqu, 0, sizeof(wrqu));
141
142 wrqu.data.length = p - buff;
143
144 wrqu.data.length = (wrqu.data.length < IW_CUSTOM_MAX) ? wrqu.data.length : IW_CUSTOM_MAX;
145
146 RTW_INFO("%s\n", __FUNCTION__);
147
148 #ifndef CONFIG_IOCTL_CFG80211
149 wireless_send_event(padapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
150 #endif
151
152 if (buff)
153 rtw_mfree(buff, IW_CUSTOM_MAX);
154
155 }
156 #endif
157
158 #ifdef CONFIG_SUPPORT_HW_WPS_PBC
rtw_request_wps_pbc_event(_adapter * padapter)159 void rtw_request_wps_pbc_event(_adapter *padapter)
160 {
161 #ifdef RTK_DMP_PLATFORM
162 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12))
163 kobject_uevent(&padapter->pnetdev->dev.kobj, KOBJ_NET_PBC);
164 #else
165 kobject_hotplug(&padapter->pnetdev->class_dev.kobj, KOBJ_NET_PBC);
166 #endif
167 #else
168
169 if (padapter->pid[0] == 0) {
170 /* 0 is the default value and it means the application monitors the HW PBC doesn't privde its pid to driver. */
171 return;
172 }
173
174 rtw_signal_process(padapter->pid[0], SIGUSR1);
175
176 #endif
177
178 rtw_led_control(padapter, LED_CTL_START_WPS_BOTTON);
179 }
180 #endif/* #ifdef CONFIG_SUPPORT_HW_WPS_PBC */
181
indicate_wx_scan_complete_event(_adapter * padapter)182 void indicate_wx_scan_complete_event(_adapter *padapter)
183 {
184 union iwreq_data wrqu;
185
186 _rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
187
188 /* RTW_INFO("+rtw_indicate_wx_scan_complete_event\n"); */
189 #ifndef CONFIG_IOCTL_CFG80211
190 wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL);
191 #endif
192 }
193
194
rtw_indicate_wx_assoc_event(_adapter * padapter)195 void rtw_indicate_wx_assoc_event(_adapter *padapter)
196 {
197 union iwreq_data wrqu;
198 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
199 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
200 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
201 WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network));
202
203 _rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
204
205 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
206
207 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)
208 _rtw_memcpy(wrqu.ap_addr.sa_data, pnetwork->MacAddress, ETH_ALEN);
209 else
210 _rtw_memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
211
212 RTW_PRINT("assoc success\n");
213 #ifndef CONFIG_IOCTL_CFG80211
214 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
215 #endif
216 }
217
rtw_indicate_wx_disassoc_event(_adapter * padapter)218 void rtw_indicate_wx_disassoc_event(_adapter *padapter)
219 {
220 union iwreq_data wrqu;
221
222 _rtw_memset(&wrqu, 0, sizeof(union iwreq_data));
223
224 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
225 _rtw_memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
226
227 #ifndef CONFIG_IOCTL_CFG80211
228 RTW_PRINT("indicate disassoc\n");
229 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
230 #endif
231 }
232
233 /*
234 uint rtw_is_cckrates_included(u8 *rate)
235 {
236 u32 i = 0;
237
238 while(rate[i]!=0)
239 {
240 if ( (((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) ||
241 (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22) )
242 return _TRUE;
243 i++;
244 }
245
246 return _FALSE;
247 }
248
249 uint rtw_is_cckratesonly_included(u8 *rate)
250 {
251 u32 i = 0;
252
253 while(rate[i]!=0)
254 {
255 if ( (((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
256 (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22) )
257 return _FALSE;
258 i++;
259 }
260
261 return _TRUE;
262 }
263 */
264
265 #ifdef CONFIG_IOCTL_WEXT
search_p2p_wfd_ie(_adapter * padapter,struct iw_request_info * info,struct wlan_network * pnetwork,char * start,char * stop)266 static int search_p2p_wfd_ie(_adapter *padapter,
267 struct iw_request_info *info, struct wlan_network *pnetwork,
268 char *start, char *stop)
269 {
270 #ifdef CONFIG_P2P
271 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
272 #ifdef CONFIG_WFD
273 if (SCAN_RESULT_ALL == pwdinfo->wfd_info->scan_result_type) {
274
275 } else if ((SCAN_RESULT_P2P_ONLY == pwdinfo->wfd_info->scan_result_type) ||
276 (SCAN_RESULT_WFD_TYPE == pwdinfo->wfd_info->scan_result_type))
277 #endif /* CONFIG_WFD */
278 {
279 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
280 u32 blnGotP2PIE = _FALSE;
281
282 /* User is doing the P2P device discovery */
283 /* The prefix of SSID should be "DIRECT-" and the IE should contains the P2P IE. */
284 /* If not, the driver should ignore this AP and go to the next AP. */
285
286 /* Verifying the SSID */
287 if (_rtw_memcmp(pnetwork->network.Ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN)) {
288 u32 p2pielen = 0;
289
290 /* Verifying the P2P IE */
291 if (rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen))
292 blnGotP2PIE = _TRUE;
293 }
294
295 if (blnGotP2PIE == _FALSE)
296 return _FALSE;
297
298 }
299 }
300
301 #ifdef CONFIG_WFD
302 if (SCAN_RESULT_WFD_TYPE == pwdinfo->wfd_info->scan_result_type) {
303 u32 blnGotWFD = _FALSE;
304 u8 *wfd_ie;
305 uint wfd_ielen = 0;
306
307 wfd_ie = rtw_bss_ex_get_wfd_ie(&pnetwork->network, NULL, &wfd_ielen);
308 if (wfd_ie) {
309 u8 *wfd_devinfo;
310 uint wfd_devlen;
311
312 wfd_devinfo = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, NULL, &wfd_devlen);
313 if (wfd_devinfo) {
314 if (pwdinfo->wfd_info->wfd_device_type == WFD_DEVINFO_PSINK) {
315 /* the first two bits will indicate the WFD device type */
316 if ((wfd_devinfo[1] & 0x03) == WFD_DEVINFO_SOURCE) {
317 /* If this device is Miracast PSink device, the scan reuslt should just provide the Miracast source. */
318 blnGotWFD = _TRUE;
319 }
320 } else if (pwdinfo->wfd_info->wfd_device_type == WFD_DEVINFO_SOURCE) {
321 /* the first two bits will indicate the WFD device type */
322 if ((wfd_devinfo[1] & 0x03) == WFD_DEVINFO_PSINK) {
323 /* If this device is Miracast source device, the scan reuslt should just provide the Miracast PSink. */
324 /* Todo: How about the SSink?! */
325 blnGotWFD = _TRUE;
326 }
327 }
328 }
329 }
330
331 if (blnGotWFD == _FALSE)
332 return _FALSE;
333 }
334 #endif /* CONFIG_WFD */
335
336 #endif /* CONFIG_P2P */
337 return _TRUE;
338 }
iwe_stream_mac_addr_proess(_adapter * padapter,struct iw_request_info * info,struct wlan_network * pnetwork,char * start,char * stop,struct iw_event * iwe)339 static inline char *iwe_stream_mac_addr_proess(_adapter *padapter,
340 struct iw_request_info *info, struct wlan_network *pnetwork,
341 char *start, char *stop, struct iw_event *iwe)
342 {
343 /* AP MAC address */
344 iwe->cmd = SIOCGIWAP;
345 iwe->u.ap_addr.sa_family = ARPHRD_ETHER;
346
347 _rtw_memcpy(iwe->u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
348 start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_ADDR_LEN);
349 return start;
350 }
iwe_stream_essid_proess(_adapter * padapter,struct iw_request_info * info,struct wlan_network * pnetwork,char * start,char * stop,struct iw_event * iwe)351 static inline char *iwe_stream_essid_proess(_adapter *padapter,
352 struct iw_request_info *info, struct wlan_network *pnetwork,
353 char *start, char *stop, struct iw_event *iwe)
354 {
355
356 /* Add the ESSID */
357 iwe->cmd = SIOCGIWESSID;
358 iwe->u.data.flags = 1;
359 iwe->u.data.length = min((u16)pnetwork->network.Ssid.SsidLength, (u16)32);
360 start = iwe_stream_add_point(info, start, stop, iwe, pnetwork->network.Ssid.Ssid);
361 return start;
362 }
363
iwe_stream_chan_process(_adapter * padapter,struct iw_request_info * info,struct wlan_network * pnetwork,char * start,char * stop,struct iw_event * iwe)364 static inline char *iwe_stream_chan_process(_adapter *padapter,
365 struct iw_request_info *info, struct wlan_network *pnetwork,
366 char *start, char *stop, struct iw_event *iwe)
367 {
368 if (pnetwork->network.Configuration.DSConfig < 1 /*|| pnetwork->network.Configuration.DSConfig>14*/)
369 pnetwork->network.Configuration.DSConfig = 1;
370
371 /* Add frequency/channel */
372 iwe->cmd = SIOCGIWFREQ;
373 iwe->u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
374 iwe->u.freq.e = 1;
375 iwe->u.freq.i = pnetwork->network.Configuration.DSConfig;
376 start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_FREQ_LEN);
377 return start;
378 }
iwe_stream_mode_process(_adapter * padapter,struct iw_request_info * info,struct wlan_network * pnetwork,char * start,char * stop,struct iw_event * iwe,u16 cap)379 static inline char *iwe_stream_mode_process(_adapter *padapter,
380 struct iw_request_info *info, struct wlan_network *pnetwork,
381 char *start, char *stop, struct iw_event *iwe, u16 cap)
382 {
383 /* Add mode */
384 if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
385 iwe->cmd = SIOCGIWMODE;
386 if (cap & WLAN_CAPABILITY_BSS)
387 iwe->u.mode = IW_MODE_MASTER;
388 else
389 iwe->u.mode = IW_MODE_ADHOC;
390
391 start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_UINT_LEN);
392 }
393 return start;
394 }
iwe_stream_encryption_process(_adapter * padapter,struct iw_request_info * info,struct wlan_network * pnetwork,char * start,char * stop,struct iw_event * iwe,u16 cap)395 static inline char *iwe_stream_encryption_process(_adapter *padapter,
396 struct iw_request_info *info, struct wlan_network *pnetwork,
397 char *start, char *stop, struct iw_event *iwe, u16 cap)
398 {
399
400 /* Add encryption capability */
401 iwe->cmd = SIOCGIWENCODE;
402 if (cap & WLAN_CAPABILITY_PRIVACY)
403 iwe->u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
404 else
405 iwe->u.data.flags = IW_ENCODE_DISABLED;
406 iwe->u.data.length = 0;
407 start = iwe_stream_add_point(info, start, stop, iwe, pnetwork->network.Ssid.Ssid);
408 return start;
409
410 }
411
iwe_stream_protocol_process(_adapter * padapter,struct iw_request_info * info,struct wlan_network * pnetwork,char * start,char * stop,struct iw_event * iwe)412 static inline char *iwe_stream_protocol_process(_adapter *padapter,
413 struct iw_request_info *info, struct wlan_network *pnetwork,
414 char *start, char *stop, struct iw_event *iwe)
415 {
416 u16 ht_cap = _FALSE, vht_cap = _FALSE;
417 u32 ht_ielen = 0, vht_ielen = 0;
418 char *p;
419 u8 ie_offset = (pnetwork->network.Reserved[0] == BSS_TYPE_PROB_REQ ? 0 : 12); /* Probe Request */
420
421 #ifdef CONFIG_80211N_HT
422 /* parsing HT_CAP_IE */
423 if(padapter->registrypriv.ht_enable && is_supported_ht(padapter->registrypriv.wireless_mode)) {
424 p = rtw_get_ie(&pnetwork->network.IEs[ie_offset], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength - ie_offset);
425 if (p && ht_ielen > 0)
426 ht_cap = _TRUE;
427 }
428 #endif
429
430 #ifdef CONFIG_80211AC_VHT
431 /* parsing VHT_CAP_IE */
432 if(padapter->registrypriv.wireless_mode & WIRELESS_11AC) {
433 p = rtw_get_ie(&pnetwork->network.IEs[ie_offset], EID_VHTCapability, &vht_ielen, pnetwork->network.IELength - ie_offset);
434 if (p && vht_ielen > 0)
435 vht_cap = _TRUE;
436 }
437 #endif
438 /* Add the protocol name */
439 iwe->cmd = SIOCGIWNAME;
440 if ((rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates)) == _TRUE) {
441 if (ht_cap == _TRUE)
442 snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11bn");
443 else
444 snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11b");
445 } else if ((rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates)) == _TRUE) {
446 if (ht_cap == _TRUE)
447 snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11bgn");
448 else
449 snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11bg");
450 } else {
451 if (pnetwork->network.Configuration.DSConfig > 14) {
452 #ifdef CONFIG_80211AC_VHT
453 if (vht_cap == _TRUE)
454 snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11AC");
455 else
456 #endif
457 {
458 if (ht_cap == _TRUE)
459 snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11an");
460 else
461 snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11a");
462 }
463 } else {
464 if (ht_cap == _TRUE)
465 snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11gn");
466 else
467 snprintf(iwe->u.name, IFNAMSIZ, "IEEE 802.11g");
468 }
469 }
470 start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_CHAR_LEN);
471 return start;
472 }
473
iwe_stream_rate_process(_adapter * padapter,struct iw_request_info * info,struct wlan_network * pnetwork,char * start,char * stop,struct iw_event * iwe)474 static inline char *iwe_stream_rate_process(_adapter *padapter,
475 struct iw_request_info *info, struct wlan_network *pnetwork,
476 char *start, char *stop, struct iw_event *iwe)
477 {
478 u32 ht_ielen = 0, vht_ielen = 0;
479 char *p;
480 u16 max_rate = 0, rate, ht_cap = _FALSE, vht_cap = _FALSE;
481 u32 i = 0;
482 u8 bw_40MHz = 0, short_GI = 0, bw_160MHz = 0, vht_highest_rate = 0;
483 u16 mcs_rate = 0, vht_data_rate = 0;
484 char custom[MAX_CUSTOM_LEN] = {0};
485 u8 ie_offset = (pnetwork->network.Reserved[0] == BSS_TYPE_PROB_REQ ? 0 : 12); /* Probe Request */
486
487 /* parsing HT_CAP_IE */
488 if(is_supported_ht(padapter->registrypriv.wireless_mode)) {
489 p = rtw_get_ie(&pnetwork->network.IEs[ie_offset], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength - ie_offset);
490 if (p && ht_ielen > 0) {
491 struct rtw_ieee80211_ht_cap *pht_capie;
492 ht_cap = _TRUE;
493 pht_capie = (struct rtw_ieee80211_ht_cap *)(p + 2);
494 _rtw_memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
495 bw_40MHz = (pht_capie->cap_info & IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
496 short_GI = (pht_capie->cap_info & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
497 }
498 }
499 #ifdef CONFIG_80211AC_VHT
500 /* parsing VHT_CAP_IE */
501 if(padapter->registrypriv.wireless_mode & WIRELESS_11AC){
502 p = rtw_get_ie(&pnetwork->network.IEs[ie_offset], EID_VHTCapability, &vht_ielen, pnetwork->network.IELength - ie_offset);
503 if (p && vht_ielen > 0) {
504 u8 mcs_map[2];
505
506 vht_cap = _TRUE;
507 bw_160MHz = GET_VHT_CAPABILITY_ELE_CHL_WIDTH(p + 2);
508 if (bw_160MHz)
509 short_GI = GET_VHT_CAPABILITY_ELE_SHORT_GI160M(p + 2);
510 else
511 short_GI = GET_VHT_CAPABILITY_ELE_SHORT_GI80M(p + 2);
512
513 _rtw_memcpy(mcs_map, GET_VHT_CAPABILITY_ELE_TX_MCS(p + 2), 2);
514
515 vht_highest_rate = rtw_get_vht_highest_rate(mcs_map);
516 vht_data_rate = rtw_vht_mcs_to_data_rate(CHANNEL_WIDTH_80, short_GI, vht_highest_rate);
517 }
518 }
519 #endif
520
521 /*Add basic and extended rates */
522 p = custom;
523 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
524 while (pnetwork->network.SupportedRates[i] != 0) {
525 rate = pnetwork->network.SupportedRates[i] & 0x7F;
526 if (rate > max_rate)
527 max_rate = rate;
528 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
529 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
530 i++;
531 }
532 #ifdef CONFIG_80211AC_VHT
533 if (vht_cap == _TRUE)
534 max_rate = vht_data_rate;
535 else
536 #endif
537 if (ht_cap == _TRUE) {
538 if (mcs_rate & 0x8000) /* MCS15 */
539 max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130);
540
541 else if (mcs_rate & 0x0080) /* MCS7 */
542 max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65);
543 else { /* default MCS7 */
544 /* RTW_INFO("wx_get_scan, mcs_rate_bitmap=0x%x\n", mcs_rate); */
545 max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65);
546 }
547
548 max_rate = max_rate * 2; /* Mbps/2; */
549 }
550
551 iwe->cmd = SIOCGIWRATE;
552 iwe->u.bitrate.fixed = iwe->u.bitrate.disabled = 0;
553 iwe->u.bitrate.value = max_rate * 500000;
554 start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_PARAM_LEN);
555 return start ;
556 }
557
iwe_stream_wpa_wpa2_process(_adapter * padapter,struct iw_request_info * info,struct wlan_network * pnetwork,char * start,char * stop,struct iw_event * iwe)558 static inline char *iwe_stream_wpa_wpa2_process(_adapter *padapter,
559 struct iw_request_info *info, struct wlan_network *pnetwork,
560 char *start, char *stop, struct iw_event *iwe)
561 {
562 int buf_size = MAX_WPA_IE_LEN * 2;
563 /* u8 pbuf[buf_size]={0}; */
564 u8 *pbuf = rtw_zmalloc(buf_size);
565
566 u8 wpa_ie[255] = {0}, rsn_ie[255] = {0};
567 u16 i, wpa_len = 0, rsn_len = 0;
568 u8 *p;
569 sint out_len = 0;
570
571
572 if (pbuf) {
573 p = pbuf;
574
575 /* parsing WPA/WPA2 IE */
576 if (pnetwork->network.Reserved[0] != BSS_TYPE_PROB_REQ) { /* Probe Request */
577 out_len = rtw_get_sec_ie(pnetwork->network.IEs , pnetwork->network.IELength, rsn_ie, &rsn_len, wpa_ie, &wpa_len);
578
579 if (wpa_len > 0) {
580
581 _rtw_memset(pbuf, 0, buf_size);
582 p += sprintf(p, "wpa_ie=");
583 for (i = 0; i < wpa_len; i++)
584 p += sprintf(p, "%02x", wpa_ie[i]);
585
586 if (wpa_len > 100) {
587 printk("-----------------Len %d----------------\n", wpa_len);
588 for (i = 0; i < wpa_len; i++)
589 printk("%02x ", wpa_ie[i]);
590 printk("\n");
591 printk("-----------------Len %d----------------\n", wpa_len);
592 }
593
594 _rtw_memset(iwe, 0, sizeof(*iwe));
595 iwe->cmd = IWEVCUSTOM;
596 iwe->u.data.length = strlen(pbuf);
597 start = iwe_stream_add_point(info, start, stop, iwe, pbuf);
598
599 _rtw_memset(iwe, 0, sizeof(*iwe));
600 iwe->cmd = IWEVGENIE;
601 iwe->u.data.length = wpa_len;
602 start = iwe_stream_add_point(info, start, stop, iwe, wpa_ie);
603 }
604 if (rsn_len > 0) {
605
606 _rtw_memset(pbuf, 0, buf_size);
607 p += sprintf(p, "rsn_ie=");
608 for (i = 0; i < rsn_len; i++)
609 p += sprintf(p, "%02x", rsn_ie[i]);
610 _rtw_memset(iwe, 0, sizeof(*iwe));
611 iwe->cmd = IWEVCUSTOM;
612 iwe->u.data.length = strlen(pbuf);
613 start = iwe_stream_add_point(info, start, stop, iwe, pbuf);
614
615 _rtw_memset(iwe, 0, sizeof(*iwe));
616 iwe->cmd = IWEVGENIE;
617 iwe->u.data.length = rsn_len;
618 start = iwe_stream_add_point(info, start, stop, iwe, rsn_ie);
619 }
620 }
621
622 rtw_mfree(pbuf, buf_size);
623 }
624 return start;
625 }
626
iwe_stream_wps_process(_adapter * padapter,struct iw_request_info * info,struct wlan_network * pnetwork,char * start,char * stop,struct iw_event * iwe)627 static inline char *iwe_stream_wps_process(_adapter *padapter,
628 struct iw_request_info *info, struct wlan_network *pnetwork,
629 char *start, char *stop, struct iw_event *iwe)
630 {
631 /* parsing WPS IE */
632 uint cnt = 0, total_ielen;
633 u8 *wpsie_ptr = NULL;
634 uint wps_ielen = 0;
635 u8 ie_offset = (pnetwork->network.Reserved[0] == BSS_TYPE_PROB_REQ ? 0 : 12);
636
637 u8 *ie_ptr = pnetwork->network.IEs + ie_offset;
638 total_ielen = pnetwork->network.IELength - ie_offset;
639
640 if (pnetwork->network.Reserved[0] == BSS_TYPE_PROB_REQ) { /* Probe Request */
641 ie_ptr = pnetwork->network.IEs;
642 total_ielen = pnetwork->network.IELength;
643 } else { /* Beacon or Probe Respones */
644 ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
645 total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
646 }
647 while (cnt < total_ielen) {
648 if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) {
649 wpsie_ptr = &ie_ptr[cnt];
650 iwe->cmd = IWEVGENIE;
651 iwe->u.data.length = (u16)wps_ielen;
652 start = iwe_stream_add_point(info, start, stop, iwe, wpsie_ptr);
653 }
654 cnt += ie_ptr[cnt + 1] + 2; /* goto next */
655 }
656 return start;
657 }
658
iwe_stream_wapi_process(_adapter * padapter,struct iw_request_info * info,struct wlan_network * pnetwork,char * start,char * stop,struct iw_event * iwe)659 static inline char *iwe_stream_wapi_process(_adapter *padapter,
660 struct iw_request_info *info, struct wlan_network *pnetwork,
661 char *start, char *stop, struct iw_event *iwe)
662 {
663 #ifdef CONFIG_WAPI_SUPPORT
664 char *p;
665
666 if (pnetwork->network.Reserved[0] != BSS_TYPE_PROB_REQ) { /* Probe Request */
667 sint out_len_wapi = 0;
668 /* here use static for stack size */
669 static u8 buf_wapi[MAX_WAPI_IE_LEN * 2] = {0};
670 static u8 wapi_ie[MAX_WAPI_IE_LEN] = {0};
671 u16 wapi_len = 0;
672 u16 i;
673
674 out_len_wapi = rtw_get_wapi_ie(pnetwork->network.IEs , pnetwork->network.IELength, wapi_ie, &wapi_len);
675
676 RTW_INFO("rtw_wx_get_scan: %s ", pnetwork->network.Ssid.Ssid);
677 RTW_INFO("rtw_wx_get_scan: ssid = %d ", wapi_len);
678
679
680 if (wapi_len > 0) {
681 p = buf_wapi;
682 /* _rtw_memset(buf_wapi, 0, MAX_WAPI_IE_LEN*2); */
683 p += sprintf(p, "wapi_ie=");
684 for (i = 0; i < wapi_len; i++)
685 p += sprintf(p, "%02x", wapi_ie[i]);
686
687 _rtw_memset(iwe, 0, sizeof(*iwe));
688 iwe->cmd = IWEVCUSTOM;
689 iwe->u.data.length = strlen(buf_wapi);
690 start = iwe_stream_add_point(info, start, stop, iwe, buf_wapi);
691
692 _rtw_memset(iwe, 0, sizeof(*iwe));
693 iwe->cmd = IWEVGENIE;
694 iwe->u.data.length = wapi_len;
695 start = iwe_stream_add_point(info, start, stop, iwe, wapi_ie);
696 }
697 }
698 #endif/* #ifdef CONFIG_WAPI_SUPPORT */
699 return start;
700 }
701
iwe_stream_rssi_process(_adapter * padapter,struct iw_request_info * info,struct wlan_network * pnetwork,char * start,char * stop,struct iw_event * iwe)702 static inline char *iwe_stream_rssi_process(_adapter *padapter,
703 struct iw_request_info *info, struct wlan_network *pnetwork,
704 char *start, char *stop, struct iw_event *iwe)
705 {
706 u8 ss, sq;
707 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
708 #ifdef CONFIG_BACKGROUND_NOISE_MONITOR
709 s16 noise = 0;
710 #endif
711
712 /* Add quality statistics */
713 iwe->cmd = IWEVQUAL;
714 iwe->u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED
715 #ifdef CONFIG_BACKGROUND_NOISE_MONITOR
716 | IW_QUAL_NOISE_UPDATED
717 #else
718 | IW_QUAL_NOISE_INVALID
719 #endif
720 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
721 | IW_QUAL_DBM
722 #endif
723 ;
724
725 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE &&
726 is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) {
727 ss = padapter->recvpriv.signal_strength;
728 sq = padapter->recvpriv.signal_qual;
729 } else {
730 ss = pnetwork->network.PhyInfo.SignalStrength;
731 sq = pnetwork->network.PhyInfo.SignalQuality;
732 }
733
734
735 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
736 iwe->u.qual.level = (u8) translate_percentage_to_dbm(ss); /* dbm */
737 #else
738 iwe->u.qual.level = (u8)ss; /* % */
739 #endif
740
741 iwe->u.qual.qual = (u8)sq; /* signal quality */
742
743 #ifdef CONFIG_PLATFORM_ROCKCHIPS
744 iwe->u.qual.noise = -100; /* noise level suggest by zhf@rockchips */
745 #else
746 #ifdef CONFIG_BACKGROUND_NOISE_MONITOR
747 if (IS_NM_ENABLE(padapter)) {
748 noise = rtw_noise_query_by_chan_num(padapter, pnetwork->network.Configuration.DSConfig);
749 #ifndef CONFIG_SIGNAL_DISPLAY_DBM
750 noise = translate_dbm_to_percentage(noise);/*percentage*/
751 #endif
752 iwe->u.qual.noise = noise;
753 }
754 #else
755 iwe->u.qual.noise = 0; /* noise level */
756 #endif
757 #endif /* CONFIG_PLATFORM_ROCKCHIPS */
758
759 /* RTW_INFO("iqual=%d, ilevel=%d, inoise=%d, iupdated=%d\n", iwe.u.qual.qual, iwe.u.qual.level , iwe.u.qual.noise, iwe.u.qual.updated); */
760
761 start = iwe_stream_add_event(info, start, stop, iwe, IW_EV_QUAL_LEN);
762 return start;
763 }
764
iwe_stream_net_rsv_process(_adapter * padapter,struct iw_request_info * info,struct wlan_network * pnetwork,char * start,char * stop,struct iw_event * iwe)765 static inline char *iwe_stream_net_rsv_process(_adapter *padapter,
766 struct iw_request_info *info, struct wlan_network *pnetwork,
767 char *start, char *stop, struct iw_event *iwe)
768 {
769 u8 buf[32] = {0};
770 u8 *p, *pos;
771 p = buf;
772 pos = pnetwork->network.Reserved;
773
774 p += sprintf(p, "fm=%02X%02X", pos[1], pos[0]);
775 _rtw_memset(iwe, 0, sizeof(*iwe));
776 iwe->cmd = IWEVCUSTOM;
777 iwe->u.data.length = strlen(buf);
778 start = iwe_stream_add_point(info, start, stop, iwe, buf);
779 return start;
780 }
781
translate_scan(_adapter * padapter,struct iw_request_info * info,struct wlan_network * pnetwork,char * start,char * stop)782 static char *translate_scan(_adapter *padapter,
783 struct iw_request_info *info, struct wlan_network *pnetwork,
784 char *start, char *stop)
785 {
786 struct iw_event iwe;
787 u16 cap = 0;
788 _rtw_memset(&iwe, 0, sizeof(iwe));
789
790 if (_FALSE == search_p2p_wfd_ie(padapter, info, pnetwork, start, stop))
791 return start;
792
793 start = iwe_stream_mac_addr_proess(padapter, info, pnetwork, start, stop, &iwe);
794 start = iwe_stream_essid_proess(padapter, info, pnetwork, start, stop, &iwe);
795 start = iwe_stream_protocol_process(padapter, info, pnetwork, start, stop, &iwe);
796 if (pnetwork->network.Reserved[0] == BSS_TYPE_PROB_REQ) /* Probe Request */
797 cap = 0;
798 else {
799 _rtw_memcpy((u8 *)&cap, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
800 cap = le16_to_cpu(cap);
801 }
802
803 start = iwe_stream_mode_process(padapter, info, pnetwork, start, stop, &iwe, cap);
804 start = iwe_stream_chan_process(padapter, info, pnetwork, start, stop, &iwe);
805 start = iwe_stream_encryption_process(padapter, info, pnetwork, start, stop, &iwe, cap);
806 start = iwe_stream_rate_process(padapter, info, pnetwork, start, stop, &iwe);
807 start = iwe_stream_wpa_wpa2_process(padapter, info, pnetwork, start, stop, &iwe);
808 start = iwe_stream_wps_process(padapter, info, pnetwork, start, stop, &iwe);
809 start = iwe_stream_wapi_process(padapter, info, pnetwork, start, stop, &iwe);
810 start = iwe_stream_rssi_process(padapter, info, pnetwork, start, stop, &iwe);
811 start = iwe_stream_net_rsv_process(padapter, info, pnetwork, start, stop, &iwe);
812
813 return start;
814 }
815
wpa_set_auth_algs(struct net_device * dev,u32 value)816 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
817 {
818 _adapter *padapter = (_adapter *) rtw_netdev_priv(dev);
819 int ret = 0;
820
821 if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
822 RTW_INFO("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY and AUTH_ALG_OPEN_SYSTEM [value:0x%x]\n", value);
823 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
824 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
825 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
826 } else if (value & AUTH_ALG_SHARED_KEY) {
827 RTW_INFO("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY [value:0x%x]\n", value);
828 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
829
830 #ifdef CONFIG_PLATFORM_MT53XX
831 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
832 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
833 #else
834 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
835 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
836 #endif
837 } else if (value & AUTH_ALG_OPEN_SYSTEM) {
838 RTW_INFO("wpa_set_auth_algs, AUTH_ALG_OPEN_SYSTEM\n");
839 /* padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; */
840 if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
841 #ifdef CONFIG_PLATFORM_MT53XX
842 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
843 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
844 #else
845 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
846 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
847 #endif
848 }
849
850 } else if (value & AUTH_ALG_LEAP)
851 RTW_INFO("wpa_set_auth_algs, AUTH_ALG_LEAP\n");
852 else {
853 RTW_INFO("wpa_set_auth_algs, error!\n");
854 ret = -EINVAL;
855 }
856
857 return ret;
858
859 }
860
wpa_set_encryption(struct net_device * dev,struct ieee_param * param,u32 param_len)861 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
862 {
863 int ret = 0;
864 u32 wep_key_idx, wep_key_len;
865 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
866 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
867 struct security_priv *psecuritypriv = &padapter->securitypriv;
868 #ifdef CONFIG_P2P
869 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
870 #endif /* CONFIG_P2P */
871
872
873 param->u.crypt.err = 0;
874 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
875
876 if (param_len < (u32)((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) {
877 ret = -EINVAL;
878 goto exit;
879 }
880
881 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
882 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
883 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
884
885 if (param->u.crypt.idx >= WEP_KEYS
886 #ifdef CONFIG_IEEE80211W
887 && param->u.crypt.idx > BIP_MAX_KEYID
888 #endif /* CONFIG_IEEE80211W */
889 ) {
890 ret = -EINVAL;
891 goto exit;
892 }
893 } else {
894 #ifdef CONFIG_WAPI_SUPPORT
895 if (strcmp(param->u.crypt.alg, "SMS4"))
896 #endif
897 {
898 ret = -EINVAL;
899 goto exit;
900 }
901 }
902
903 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
904 RTW_INFO("wpa_set_encryption, crypt.alg = WEP\n");
905
906 wep_key_idx = param->u.crypt.idx;
907 wep_key_len = param->u.crypt.key_len;
908
909 if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
910 ret = -EINVAL;
911 goto exit;
912 }
913
914 if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
915 /* wep default key has not been set, so use this key index as default key.*/
916
917 wep_key_len = wep_key_len <= 5 ? 5 : 13;
918
919 psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
920 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
921 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
922
923 if (wep_key_len == 13) {
924 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
925 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
926 }
927
928 psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
929 }
930
931 _rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), param->u.crypt.key, wep_key_len);
932
933 psecuritypriv->dot11DefKeylen[wep_key_idx] = wep_key_len;
934
935 psecuritypriv->key_mask |= BIT(wep_key_idx);
936
937 padapter->mlmeextpriv.mlmext_info.key_index = wep_key_idx;
938 goto exit;
939 }
940
941 if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /* 802_1x */
942 struct sta_info *psta, *pbcmc_sta;
943 struct sta_priv *pstapriv = &padapter->stapriv;
944
945 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == _TRUE) { /* sta mode */
946 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
947 if (psta == NULL) {
948 /* DEBUG_ERR( ("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
949 } else {
950 /* Jeff: don't disable ieee8021x_blocked while clearing key */
951 if (strcmp(param->u.crypt.alg, "none") != 0)
952 psta->ieee8021x_blocked = _FALSE;
953
954 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
955 (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
956 psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
957
958 if (param->u.crypt.set_tx == 1) { /* pairwise key */
959 RTW_INFO(FUNC_ADPT_FMT" set %s PTK idx:%u, len:%u\n"
960 , FUNC_ADPT_ARG(padapter), param->u.crypt.alg, param->u.crypt.idx, param->u.crypt.key_len);
961 _rtw_memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
962 if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
963 _rtw_memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
964 _rtw_memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
965 padapter->securitypriv.busetkipkey = _FALSE;
966 }
967 psta->dot11txpn.val = RTW_GET_LE64(param->u.crypt.seq);
968 psta->dot11rxpn.val = RTW_GET_LE64(param->u.crypt.seq);
969 psta->bpairwise_key_installed = _TRUE;
970 rtw_setstakey_cmd(padapter, psta, UNICAST_KEY, _TRUE);
971
972 } else { /* group key */
973 if (strcmp(param->u.crypt.alg, "TKIP") == 0 || strcmp(param->u.crypt.alg, "CCMP") == 0) {
974 RTW_INFO(FUNC_ADPT_FMT" set %s GTK idx:%u, len:%u\n"
975 , FUNC_ADPT_ARG(padapter), param->u.crypt.alg, param->u.crypt.idx, param->u.crypt.key_len);
976 _rtw_memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key,
977 (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
978 /* only TKIP group key need to install this */
979 if (param->u.crypt.key_len > 16) {
980 _rtw_memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
981 _rtw_memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
982 }
983 padapter->securitypriv.binstallGrpkey = _TRUE;
984 if (param->u.crypt.idx < 4)
985 _rtw_memcpy(padapter->securitypriv.iv_seq[param->u.crypt.idx], param->u.crypt.seq, 8);
986 padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
987 rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1, _TRUE);
988
989 #ifdef CONFIG_IEEE80211W
990 } else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
991 RTW_INFO(FUNC_ADPT_FMT" set IGTK idx:%u, len:%u\n"
992 , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
993 _rtw_memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key,
994 (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
995 psecuritypriv->dot11wBIPKeyid = param->u.crypt.idx;
996 psecuritypriv->dot11wBIPrxpn.val = RTW_GET_LE64(param->u.crypt.seq);
997 psecuritypriv->binstallBIPkey = _TRUE;
998 #endif /* CONFIG_IEEE80211W */
999
1000 }
1001
1002 #ifdef CONFIG_P2P
1003 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
1004 rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_DONE);
1005 #endif /* CONFIG_P2P */
1006
1007 /* WPA/WPA2 key-handshake has completed */
1008 clr_fwstate(pmlmepriv, WIFI_UNDER_KEY_HANDSHAKE);
1009 }
1010 }
1011
1012 pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
1013 if (pbcmc_sta == NULL) {
1014 /* DEBUG_ERR( ("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
1015 } else {
1016 /* Jeff: don't disable ieee8021x_blocked while clearing key */
1017 if (strcmp(param->u.crypt.alg, "none") != 0)
1018 pbcmc_sta->ieee8021x_blocked = _FALSE;
1019
1020 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
1021 (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
1022 pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
1023 }
1024 } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { /* adhoc mode */
1025 }
1026 }
1027
1028 #ifdef CONFIG_WAPI_SUPPORT
1029 if (strcmp(param->u.crypt.alg, "SMS4") == 0)
1030 rtw_wapi_set_set_encryption(padapter, param);
1031 #endif
1032
1033 exit:
1034
1035
1036 return ret;
1037 }
1038
rtw_set_wpa_ie(_adapter * padapter,char * pie,unsigned short ielen)1039 static int rtw_set_wpa_ie(_adapter *padapter, char *pie, unsigned short ielen)
1040 {
1041 u8 *buf = NULL, *pos = NULL;
1042 int group_cipher = 0, pairwise_cipher = 0;
1043 u8 mfp_opt = MFP_NO;
1044 int ret = 0;
1045 u8 null_addr[] = {0, 0, 0, 0, 0, 0};
1046 #ifdef CONFIG_P2P
1047 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1048 #endif /* CONFIG_P2P */
1049
1050 if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) {
1051 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1052 if (pie == NULL)
1053 return ret;
1054 else
1055 return -EINVAL;
1056 }
1057
1058 if (ielen) {
1059 buf = rtw_zmalloc(ielen);
1060 if (buf == NULL) {
1061 ret = -ENOMEM;
1062 goto exit;
1063 }
1064
1065 _rtw_memcpy(buf, pie , ielen);
1066
1067 /* dump */
1068 {
1069 int i;
1070 RTW_INFO("\n wpa_ie(length:%d):\n", ielen);
1071 for (i = 0; i < ielen; i = i + 8)
1072 RTW_INFO("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", buf[i], buf[i + 1], buf[i + 2], buf[i + 3], buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7]);
1073 }
1074
1075 pos = buf;
1076 if (ielen < RSN_HEADER_LEN) {
1077 ret = -1;
1078 goto exit;
1079 }
1080
1081 if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1082 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1083 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
1084 _rtw_memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
1085 }
1086
1087 if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL, NULL, &mfp_opt, NULL) == _SUCCESS) {
1088 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1089 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
1090 _rtw_memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
1091 }
1092
1093 if (group_cipher == 0)
1094 group_cipher = WPA_CIPHER_NONE;
1095 if (pairwise_cipher == 0)
1096 pairwise_cipher = WPA_CIPHER_NONE;
1097
1098 switch (group_cipher) {
1099 case WPA_CIPHER_NONE:
1100 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1101 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1102 break;
1103 case WPA_CIPHER_WEP40:
1104 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
1105 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1106 break;
1107 case WPA_CIPHER_TKIP:
1108 padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
1109 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
1110 break;
1111 case WPA_CIPHER_CCMP:
1112 padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
1113 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
1114 break;
1115 case WPA_CIPHER_WEP104:
1116 padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
1117 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1118 break;
1119 }
1120
1121 switch (pairwise_cipher) {
1122 case WPA_CIPHER_NONE:
1123 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1124 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1125 break;
1126 case WPA_CIPHER_WEP40:
1127 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1128 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1129 break;
1130 case WPA_CIPHER_TKIP:
1131 padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
1132 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
1133 break;
1134 case WPA_CIPHER_CCMP:
1135 padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
1136 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
1137 break;
1138 case WPA_CIPHER_WEP104:
1139 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
1140 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1141 break;
1142 }
1143
1144 if (mfp_opt == MFP_INVALID) {
1145 RTW_INFO(FUNC_ADPT_FMT" invalid MFP setting\n", FUNC_ADPT_ARG(padapter));
1146 ret = -EINVAL;
1147 goto exit;
1148 }
1149 padapter->securitypriv.mfp_opt = mfp_opt;
1150
1151 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1152 {/* set wps_ie */
1153 u16 cnt = 0;
1154 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
1155
1156 while (cnt < ielen) {
1157 eid = buf[cnt];
1158
1159 if ((eid == _VENDOR_SPECIFIC_IE_) && (_rtw_memcmp(&buf[cnt + 2], wps_oui, 4) == _TRUE)) {
1160 RTW_INFO("SET WPS_IE\n");
1161
1162 padapter->securitypriv.wps_ie_len = ((buf[cnt + 1] + 2) < MAX_WPS_IE_LEN) ? (buf[cnt + 1] + 2) : MAX_WPS_IE_LEN;
1163
1164 _rtw_memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
1165
1166 set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
1167
1168 #ifdef CONFIG_P2P
1169 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK))
1170 rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_ING);
1171 #endif /* CONFIG_P2P */
1172 cnt += buf[cnt + 1] + 2;
1173
1174 break;
1175 } else {
1176 cnt += buf[cnt + 1] + 2; /* goto next */
1177 }
1178 }
1179 }
1180
1181 #ifdef CONFIG_RTW_MULTI_AP
1182 padapter->multi_ap = rtw_get_multi_ap_ie_ext(buf, ielen) & MULTI_AP_BACKHAUL_STA;
1183 if (padapter->multi_ap)
1184 adapter_set_use_wds(padapter, 1);
1185 #endif
1186 }
1187
1188 /* TKIP and AES disallow multicast packets until installing group key */
1189 if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_
1190 || padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_
1191 || padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
1192 /* WPS open need to enable multicast
1193 * || check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == _TRUE) */
1194 rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr);
1195
1196
1197 exit:
1198
1199 if (buf)
1200 rtw_mfree(buf, ielen);
1201
1202 return ret;
1203 }
1204
rtw_wx_get_name(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1205 static int rtw_wx_get_name(struct net_device *dev,
1206 struct iw_request_info *info,
1207 union iwreq_data *wrqu, char *extra)
1208 {
1209 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1210 u32 ht_ielen = 0;
1211 char *p;
1212 u8 ht_cap = _FALSE, vht_cap = _FALSE;
1213 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1214 WLAN_BSSID_EX *pcur_bss = &pmlmepriv->cur_network.network;
1215 NDIS_802_11_RATES_EX *prates = NULL;
1216
1217
1218
1219 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE | WIFI_ADHOC_MASTER_STATE) == _TRUE) {
1220 /* parsing HT_CAP_IE */
1221 if( is_supported_ht(padapter->registrypriv.wireless_mode)&&(padapter->registrypriv.ht_enable)) {
1222 p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength - 12);
1223 if (p && ht_ielen > 0 )
1224 ht_cap = _TRUE;
1225 }
1226 #ifdef CONFIG_80211AC_VHT
1227 if ((padapter->registrypriv.wireless_mode & WIRELESS_11AC) &&
1228 (pmlmepriv->vhtpriv.vht_option == _TRUE))
1229 vht_cap = _TRUE;
1230 #endif
1231
1232 prates = &pcur_bss->SupportedRates;
1233 if (rtw_is_cckratesonly_included((u8 *)prates) == _TRUE) {
1234 if (ht_cap == _TRUE)
1235 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
1236 else
1237 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
1238 } else if ((rtw_is_cckrates_included((u8 *)prates)) == _TRUE) {
1239 if (ht_cap == _TRUE)
1240 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
1241 else {
1242 if(padapter->registrypriv.wireless_mode & WIRELESS_11G)
1243 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
1244 else
1245 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
1246 }
1247 } else {
1248 if (pcur_bss->Configuration.DSConfig > 14) {
1249 #ifdef CONFIG_80211AC_VHT
1250 if (vht_cap == _TRUE)
1251 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11AC");
1252 else
1253 #endif
1254 {
1255 if (ht_cap == _TRUE)
1256 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an");
1257 else
1258 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a");
1259 }
1260 } else {
1261 if (ht_cap == _TRUE)
1262 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
1263 else
1264 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
1265 }
1266 }
1267 } else {
1268 /* prates = &padapter->registrypriv.dev_network.SupportedRates; */
1269 /* snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g"); */
1270 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
1271 }
1272
1273
1274 return 0;
1275 }
1276
rtw_wx_set_freq(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1277 static int rtw_wx_set_freq(struct net_device *dev,
1278 struct iw_request_info *info,
1279 union iwreq_data *wrqu, char *extra)
1280 {
1281
1282 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1283 int exp = 1, freq = 0, div = 0;
1284
1285 rtw_ps_deny(padapter, PS_DENY_IOCTL);
1286 if (rtw_pwr_wakeup(padapter) == _FALSE)
1287 goto exit;
1288 if (wrqu->freq.m <= 1000) {
1289 if (wrqu->freq.flags == IW_FREQ_AUTO) {
1290 if (rtw_chset_search_ch(adapter_to_chset(padapter), wrqu->freq.m) > 0) {
1291 padapter->mlmeextpriv.cur_channel = wrqu->freq.m;
1292 RTW_INFO("%s: channel is auto, set to channel %d\n", __func__, wrqu->freq.m);
1293 } else {
1294 padapter->mlmeextpriv.cur_channel = 1;
1295 RTW_INFO("%s: channel is auto, Channel Plan don't match just set to channel 1\n", __func__);
1296 }
1297 } else {
1298 padapter->mlmeextpriv.cur_channel = wrqu->freq.m;
1299 RTW_INFO("%s: set to channel %d\n", __func__, padapter->mlmeextpriv.cur_channel);
1300 }
1301 } else {
1302 while (wrqu->freq.e) {
1303 exp *= 10;
1304 wrqu->freq.e--;
1305 }
1306
1307 freq = wrqu->freq.m;
1308
1309 while (!(freq % 10)) {
1310 freq /= 10;
1311 exp *= 10;
1312 }
1313
1314 /* freq unit is MHz here */
1315 div = 1000000 / exp;
1316
1317 if (div)
1318 freq /= div;
1319 else {
1320 div = exp / 1000000;
1321 freq *= div;
1322 }
1323
1324 /* If freq is invalid, rtw_freq2ch() will return channel 1 */
1325 padapter->mlmeextpriv.cur_channel = rtw_freq2ch(freq);
1326 RTW_INFO("%s: set to channel %d\n", __func__, padapter->mlmeextpriv.cur_channel);
1327 }
1328 set_channel_bwmode(padapter, padapter->mlmeextpriv.cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
1329 exit:
1330 rtw_ps_deny_cancel(padapter, PS_DENY_IOCTL);
1331
1332 return 0;
1333 }
1334
rtw_wx_get_freq(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1335 static int rtw_wx_get_freq(struct net_device *dev,
1336 struct iw_request_info *info,
1337 union iwreq_data *wrqu, char *extra)
1338 {
1339 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1340 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1341 WLAN_BSSID_EX *pcur_bss = &pmlmepriv->cur_network.network;
1342
1343 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE && check_fwstate(pmlmepriv, WIFI_MONITOR_STATE) != _TRUE) {
1344
1345 wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
1346 wrqu->freq.e = 1;
1347 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
1348
1349 } else {
1350 wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
1351 wrqu->freq.e = 1;
1352 wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
1353 }
1354
1355 return 0;
1356 }
1357
rtw_wx_set_mode(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * b)1358 static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
1359 union iwreq_data *wrqu, char *b)
1360 {
1361 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1362 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1363 NDIS_802_11_NETWORK_INFRASTRUCTURE networkType ;
1364 int ret = 0;
1365
1366
1367 if (_FAIL == rtw_pwr_wakeup(padapter)) {
1368 ret = -EPERM;
1369 goto exit;
1370 }
1371
1372 if (!rtw_is_hw_init_completed(padapter)) {
1373 ret = -EPERM;
1374 goto exit;
1375 }
1376
1377 /* initial default type */
1378 dev->type = ARPHRD_ETHER;
1379
1380 if (wrqu->mode != IW_MODE_MONITOR) {
1381 rtw_ps_deny_cancel(padapter, PS_DENY_MONITOR_MODE);
1382 }
1383
1384 switch (wrqu->mode) {
1385 #ifdef CONFIG_WIFI_MONITOR
1386 case IW_MODE_MONITOR:
1387 networkType = Ndis802_11Monitor;
1388
1389 rtw_ps_deny(padapter, PS_DENY_MONITOR_MODE);
1390 LeaveAllPowerSaveMode(padapter);
1391
1392 #if 0
1393 dev->type = ARPHRD_IEEE80211; /* IEEE 802.11 : 801 */
1394 #endif
1395
1396 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24))
1397 dev->type = ARPHRD_IEEE80211_RADIOTAP; /* IEEE 802.11 + radiotap header : 803 */
1398 RTW_INFO("set_mode = IW_MODE_MONITOR\n");
1399 #else
1400 RTW_INFO("kernel version < 2.6.24 not support IW_MODE_MONITOR\n");
1401 #endif
1402 break;
1403 #endif /* CONFIG_WIFI_MONITOR */
1404 case IW_MODE_AUTO:
1405 networkType = Ndis802_11AutoUnknown;
1406 RTW_INFO("set_mode = IW_MODE_AUTO\n");
1407 break;
1408 case IW_MODE_ADHOC:
1409 networkType = Ndis802_11IBSS;
1410 RTW_INFO("set_mode = IW_MODE_ADHOC\n");
1411 break;
1412 case IW_MODE_MASTER:
1413 networkType = Ndis802_11APMode;
1414 RTW_INFO("set_mode = IW_MODE_MASTER\n");
1415 break;
1416 case IW_MODE_INFRA:
1417 networkType = Ndis802_11Infrastructure;
1418 RTW_INFO("set_mode = IW_MODE_INFRA\n");
1419 break;
1420
1421 default:
1422 ret = -EINVAL;;
1423 goto exit;
1424 }
1425
1426 if (rtw_set_802_11_infrastructure_mode(padapter, networkType, 0) == _FALSE) {
1427
1428 ret = -EPERM;
1429 goto exit;
1430
1431 }
1432
1433 rtw_setopmode_cmd(padapter, networkType, RTW_CMDF_WAIT_ACK);
1434
1435 if (check_fwstate(pmlmepriv, WIFI_MONITOR_STATE) == _TRUE)
1436 rtw_indicate_connect(padapter);
1437
1438 exit:
1439
1440
1441 return ret;
1442
1443 }
1444
rtw_wx_get_mode(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * b)1445 static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
1446 union iwreq_data *wrqu, char *b)
1447 {
1448 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1449 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1450
1451
1452
1453 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)
1454 wrqu->mode = IW_MODE_INFRA;
1455 else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE) ||
1456 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE))
1457
1458 wrqu->mode = IW_MODE_ADHOC;
1459 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
1460 wrqu->mode = IW_MODE_MASTER;
1461 else if (check_fwstate(pmlmepriv, WIFI_MONITOR_STATE) == _TRUE)
1462 wrqu->mode = IW_MODE_MONITOR;
1463 else
1464 wrqu->mode = IW_MODE_AUTO;
1465
1466
1467 return 0;
1468
1469 }
1470
1471
rtw_wx_set_pmkid(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * extra)1472 static int rtw_wx_set_pmkid(struct net_device *dev,
1473 struct iw_request_info *a,
1474 union iwreq_data *wrqu, char *extra)
1475 {
1476 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1477 u8 j, blInserted = _FALSE;
1478 int intReturn = _FALSE;
1479 struct security_priv *psecuritypriv = &padapter->securitypriv;
1480 struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
1481 u8 strZeroMacAddress[ETH_ALEN] = { 0x00 };
1482 u8 strIssueBssid[ETH_ALEN] = { 0x00 };
1483
1484 #if 0
1485 struct iw_pmksa {
1486 __u32 cmd;
1487 struct sockaddr bssid;
1488 __u8 pmkid[IW_PMKID_LEN]; /* IW_PMKID_LEN=16 */
1489 }
1490 There are the BSSID information in the bssid.sa_data array.
1491 If cmd is IW_PMKSA_FLUSH, it means the wpa_suppplicant wants to clear all the PMKID information.
1492 If cmd is IW_PMKSA_ADD, it means the wpa_supplicant wants to add a PMKID / BSSID to driver.
1493 If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to remove a PMKID / BSSID from driver.
1494 #endif
1495
1496 _rtw_memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
1497 if (pPMK->cmd == IW_PMKSA_ADD) {
1498 RTW_INFO("[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n");
1499 if (_rtw_memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN) == _TRUE)
1500 return intReturn ;
1501 else
1502 intReturn = _TRUE;
1503 blInserted = _FALSE;
1504
1505 /* overwrite PMKID */
1506 for (j = 0 ; j < NUM_PMKID_CACHE; j++) {
1507 if (_rtw_memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN) == _TRUE) {
1508 /* BSSID is matched, the same AP => rewrite with new PMKID. */
1509
1510 RTW_INFO("[rtw_wx_set_pmkid] BSSID exists in the PMKList.\n");
1511
1512 _rtw_memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
1513 psecuritypriv->PMKIDList[j].bUsed = _TRUE;
1514 psecuritypriv->PMKIDIndex = j + 1;
1515 blInserted = _TRUE;
1516 break;
1517 }
1518 }
1519
1520 if (!blInserted) {
1521 /* Find a new entry */
1522 RTW_INFO("[rtw_wx_set_pmkid] Use the new entry index = %d for this PMKID.\n",
1523 psecuritypriv->PMKIDIndex);
1524
1525 _rtw_memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
1526 _rtw_memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
1527
1528 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = _TRUE;
1529 psecuritypriv->PMKIDIndex++ ;
1530 if (psecuritypriv->PMKIDIndex == 16)
1531 psecuritypriv->PMKIDIndex = 0;
1532 }
1533 } else if (pPMK->cmd == IW_PMKSA_REMOVE) {
1534 RTW_INFO("[rtw_wx_set_pmkid] IW_PMKSA_REMOVE!\n");
1535 intReturn = _TRUE;
1536 for (j = 0 ; j < NUM_PMKID_CACHE; j++) {
1537 if (_rtw_memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN) == _TRUE) {
1538 /* BSSID is matched, the same AP => Remove this PMKID information and reset it. */
1539 _rtw_memset(psecuritypriv->PMKIDList[j].Bssid, 0x00, ETH_ALEN);
1540 psecuritypriv->PMKIDList[j].bUsed = _FALSE;
1541 break;
1542 }
1543 }
1544 } else if (pPMK->cmd == IW_PMKSA_FLUSH) {
1545 RTW_INFO("[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n");
1546 _rtw_memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(RT_PMKID_LIST) * NUM_PMKID_CACHE);
1547 psecuritypriv->PMKIDIndex = 0;
1548 intReturn = _TRUE;
1549 }
1550 return intReturn ;
1551 }
1552
rtw_wx_get_sens(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1553 static int rtw_wx_get_sens(struct net_device *dev,
1554 struct iw_request_info *info,
1555 union iwreq_data *wrqu, char *extra)
1556 {
1557 #ifdef CONFIG_PLATFORM_ROCKCHIPS
1558 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1559 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1560
1561 /*
1562 * 20110311 Commented by Jeff
1563 * For rockchip platform's wpa_driver_wext_get_rssi
1564 */
1565 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE) {
1566 /* wrqu->sens.value=-padapter->recvpriv.signal_strength; */
1567 wrqu->sens.value = -padapter->recvpriv.rssi;
1568 /* RTW_INFO("%s: %d\n", __FUNCTION__, wrqu->sens.value); */
1569 wrqu->sens.fixed = 0; /* no auto select */
1570 } else
1571 #endif
1572 {
1573 wrqu->sens.value = 0;
1574 wrqu->sens.fixed = 0; /* no auto select */
1575 wrqu->sens.disabled = 1;
1576 }
1577 return 0;
1578 }
1579
rtw_wx_get_range(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1580 static int rtw_wx_get_range(struct net_device *dev,
1581 struct iw_request_info *info,
1582 union iwreq_data *wrqu, char *extra)
1583 {
1584 struct iw_range *range = (struct iw_range *)extra;
1585 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1586 struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
1587 u16 val;
1588 int i;
1589
1590
1591
1592 wrqu->data.length = sizeof(*range);
1593 _rtw_memset(range, 0, sizeof(*range));
1594
1595 /* Let's try to keep this struct in the same order as in
1596 * linux/include/wireless.h
1597 */
1598
1599 /* TODO: See what values we can set, and remove the ones we can't
1600 * set, or fill them with some default data.
1601 */
1602
1603 /* ~5 Mb/s real (802.11b) */
1604 range->throughput = 5 * 1000 * 1000;
1605
1606 /* TODO: Not used in 802.11b?
1607 * range->min_nwid; Minimal NWID we are able to set */
1608 /* TODO: Not used in 802.11b?
1609 * range->max_nwid; Maximal NWID we are able to set */
1610
1611 /* Old Frequency (backward compat - moved lower ) */
1612 /* range->old_num_channels;
1613 * range->old_num_frequency;
1614 * range->old_freq[6]; Filler to keep "version" at the same offset */
1615
1616 /* signal level threshold range */
1617
1618 /* Quality of link & SNR stuff */
1619 /* Quality range (link, level, noise)
1620 * If the quality is absolute, it will be in the range [0 ; max_qual],
1621 * if the quality is dBm, it will be in the range [max_qual ; 0].
1622 * Don't forget that we use 8 bit arithmetics...
1623 *
1624 * If percentage range is 0~100
1625 * Signal strength dbm range logical is -100 ~ 0
1626 * but usually value is -90 ~ -20
1627 */
1628 range->max_qual.qual = 100;
1629 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
1630 range->max_qual.level = (u8)-100;
1631 range->max_qual.noise = (u8)-100;
1632 range->max_qual.updated = IW_QUAL_ALL_UPDATED; /* Updated all three */
1633 range->max_qual.updated |= IW_QUAL_DBM;
1634 #else /* !CONFIG_SIGNAL_DISPLAY_DBM */
1635 /* percent values between 0 and 100. */
1636 range->max_qual.level = 100;
1637 range->max_qual.noise = 100;
1638 range->max_qual.updated = IW_QUAL_ALL_UPDATED; /* Updated all three */
1639 #endif /* !CONFIG_SIGNAL_DISPLAY_DBM */
1640
1641 /* This should contain the average/typical values of the quality
1642 * indicator. This should be the threshold between a "good" and
1643 * a "bad" link (example : monitor going from green to orange).
1644 * Currently, user space apps like quality monitors don't have any
1645 * way to calibrate the measurement. With this, they can split
1646 * the range between 0 and max_qual in different quality level
1647 * (using a geometric subdivision centered on the average).
1648 * I expect that people doing the user space apps will feedback
1649 * us on which value we need to put in each driver... */
1650 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
1651 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
1652 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
1653 range->avg_qual.level = (u8)-70;
1654 range->avg_qual.noise = 0;
1655 range->avg_qual.updated = IW_QUAL_ALL_UPDATED; /* Updated all three */
1656 range->avg_qual.updated |= IW_QUAL_DBM;
1657 #else /* !CONFIG_SIGNAL_DISPLAY_DBM */
1658 /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
1659 range->avg_qual.level = 30;
1660 range->avg_qual.noise = 100;
1661 range->avg_qual.updated = IW_QUAL_ALL_UPDATED; /* Updated all three */
1662 #endif /* !CONFIG_SIGNAL_DISPLAY_DBM */
1663
1664 range->num_bitrates = RATE_COUNT;
1665
1666 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
1667 range->bitrate[i] = rtw_rates[i];
1668
1669 range->min_frag = MIN_FRAG_THRESHOLD;
1670 range->max_frag = MAX_FRAG_THRESHOLD;
1671
1672 range->pm_capa = 0;
1673
1674 range->we_version_compiled = WIRELESS_EXT;
1675 range->we_version_source = 16;
1676
1677 /* range->retry_capa; What retry options are supported
1678 * range->retry_flags; How to decode max/min retry limit
1679 * range->r_time_flags; How to decode max/min retry life
1680 * range->min_retry; Minimal number of retries
1681 * range->max_retry; Maximal number of retries
1682 * range->min_r_time; Minimal retry lifetime
1683 * range->max_r_time; Maximal retry lifetime */
1684
1685 for (i = 0, val = 0; i < rfctl->max_chan_nums; i++) {
1686
1687 /* Include only legal frequencies for some countries */
1688 if (rfctl->channel_set[i].ChannelNum != 0) {
1689 range->freq[val].i = rfctl->channel_set[i].ChannelNum;
1690 range->freq[val].m = rtw_ch2freq(rfctl->channel_set[i].ChannelNum) * 100000;
1691 range->freq[val].e = 1;
1692 val++;
1693 }
1694
1695 if (val == IW_MAX_FREQUENCIES)
1696 break;
1697 }
1698
1699 range->num_channels = val;
1700 range->num_frequency = val;
1701
1702 /* Commented by Albert 2009/10/13
1703 * The following code will proivde the security capability to network manager.
1704 * If the driver doesn't provide this capability to network manager,
1705 * the WPA/WPA2 routers can't be choosen in the network manager. */
1706
1707 /*
1708 #define IW_SCAN_CAPA_NONE 0x00
1709 #define IW_SCAN_CAPA_ESSID 0x01
1710 #define IW_SCAN_CAPA_BSSID 0x02
1711 #define IW_SCAN_CAPA_CHANNEL 0x04
1712 #define IW_SCAN_CAPA_MODE 0x08
1713 #define IW_SCAN_CAPA_RATE 0x10
1714 #define IW_SCAN_CAPA_TYPE 0x20
1715 #define IW_SCAN_CAPA_TIME 0x40
1716 */
1717
1718 #if WIRELESS_EXT > 17
1719 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
1720 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
1721 #endif
1722
1723 #ifdef IW_SCAN_CAPA_ESSID /* WIRELESS_EXT > 21 */
1724 range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE | IW_SCAN_CAPA_BSSID |
1725 IW_SCAN_CAPA_CHANNEL | IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE;
1726 #endif
1727
1728
1729
1730 return 0;
1731
1732 }
1733
1734 /* set bssid flow
1735 * s1. rtw_set_802_11_infrastructure_mode()
1736 * s2. rtw_set_802_11_authentication_mode()
1737 * s3. set_802_11_encryption_mode()
1738 * 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)1739 static int rtw_wx_set_wap(struct net_device *dev,
1740 struct iw_request_info *info,
1741 union iwreq_data *awrq,
1742 char *extra)
1743 {
1744 _irqL irqL;
1745 uint ret = 0;
1746 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1747 struct sockaddr *temp = (struct sockaddr *)awrq;
1748 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1749 _list *phead;
1750 u8 *dst_bssid, *src_bssid;
1751 _queue *queue = &(pmlmepriv->scanned_queue);
1752 struct wlan_network *pnetwork = NULL;
1753 NDIS_802_11_AUTHENTICATION_MODE authmode;
1754
1755 /*
1756 #ifdef CONFIG_CONCURRENT_MODE
1757 if(padapter->adapter_type > PRIMARY_IFACE)
1758 {
1759 ret = -EINVAL;
1760 goto exit;
1761 }
1762 #endif
1763 */
1764
1765 #ifdef CONFIG_CONCURRENT_MODE
1766 if (rtw_mi_buddy_check_fwstate(padapter, WIFI_UNDER_SURVEY | WIFI_UNDER_LINKING) == _TRUE) {
1767 RTW_INFO("set bssid, but buddy_intf is under scanning or linking\n");
1768
1769 ret = -EINVAL;
1770
1771 goto exit;
1772 }
1773 #endif
1774
1775 rtw_ps_deny(padapter, PS_DENY_JOIN);
1776 if (_FAIL == rtw_pwr_wakeup(padapter)) {
1777 ret = -1;
1778 goto cancel_ps_deny;
1779 }
1780
1781 if (!padapter->bup) {
1782 ret = -1;
1783 goto cancel_ps_deny;
1784 }
1785
1786
1787 if (temp->sa_family != ARPHRD_ETHER) {
1788 ret = -EINVAL;
1789 goto cancel_ps_deny;
1790 }
1791
1792 authmode = padapter->securitypriv.ndisauthtype;
1793 _enter_critical_bh(&queue->lock, &irqL);
1794 phead = get_list_head(queue);
1795 pmlmepriv->pscanned = get_next(phead);
1796
1797 while (1) {
1798
1799 if ((rtw_end_of_queue_search(phead, pmlmepriv->pscanned)) == _TRUE) {
1800 #if 0
1801 ret = -EINVAL;
1802 goto cancel_ps_deny;
1803
1804 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE) {
1805 rtw_set_802_11_bssid(padapter, temp->sa_data);
1806 goto cancel_ps_deny;
1807 } else {
1808 ret = -EINVAL;
1809 goto cancel_ps_deny;
1810 }
1811 #endif
1812
1813 break;
1814 }
1815
1816 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
1817
1818 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1819
1820 dst_bssid = pnetwork->network.MacAddress;
1821
1822 src_bssid = temp->sa_data;
1823
1824 if ((_rtw_memcmp(dst_bssid, src_bssid, ETH_ALEN)) == _TRUE) {
1825 if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode, 0)) {
1826 ret = -1;
1827 _exit_critical_bh(&queue->lock, &irqL);
1828 goto cancel_ps_deny;
1829 }
1830
1831 break;
1832 }
1833
1834 }
1835 _exit_critical_bh(&queue->lock, &irqL);
1836
1837 rtw_set_802_11_authentication_mode(padapter, authmode);
1838 /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
1839 if (rtw_set_802_11_bssid(padapter, temp->sa_data) == _FALSE) {
1840 ret = -1;
1841 goto cancel_ps_deny;
1842 }
1843
1844 cancel_ps_deny:
1845 rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
1846
1847 #ifdef CONFIG_CONCURRENT_MODE
1848 exit:
1849 #endif
1850 return ret;
1851 }
1852
rtw_wx_get_wap(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1853 static int rtw_wx_get_wap(struct net_device *dev,
1854 struct iw_request_info *info,
1855 union iwreq_data *wrqu, char *extra)
1856 {
1857
1858 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1859 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1860 WLAN_BSSID_EX *pcur_bss = &pmlmepriv->cur_network.network;
1861
1862 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1863
1864 _rtw_memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1865
1866
1867
1868 if (((check_fwstate(pmlmepriv, WIFI_ASOC_STATE)) == _TRUE) ||
1869 ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == _TRUE) ||
1870 ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == _TRUE))
1871
1872 _rtw_memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1873 else
1874 _rtw_memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1875
1876
1877 return 0;
1878
1879 }
1880
rtw_wx_set_mlme(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1881 static int rtw_wx_set_mlme(struct net_device *dev,
1882 struct iw_request_info *info,
1883 union iwreq_data *wrqu, char *extra)
1884 {
1885 #if 0
1886 /* SIOCSIWMLME data */
1887 struct iw_mlme {
1888 __u16 cmd; /* IW_MLME_* */
1889 __u16 reason_code;
1890 struct sockaddr addr;
1891 };
1892 #endif
1893
1894 int ret = 0;
1895 u16 reason;
1896 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1897 struct iw_mlme *mlme = (struct iw_mlme *) extra;
1898
1899
1900 if (mlme == NULL)
1901 return -1;
1902
1903 RTW_INFO("%s\n", __FUNCTION__);
1904
1905 reason = cpu_to_le16(mlme->reason_code);
1906
1907
1908 RTW_INFO("%s, cmd=%d, reason=%d\n", __FUNCTION__, mlme->cmd, reason);
1909
1910
1911 switch (mlme->cmd) {
1912 case IW_MLME_DEAUTH:
1913 if (!rtw_set_802_11_disassociate(padapter))
1914 ret = -1;
1915 break;
1916
1917 case IW_MLME_DISASSOC:
1918 if (!rtw_set_802_11_disassociate(padapter))
1919 ret = -1;
1920
1921 break;
1922
1923 default:
1924 return -EOPNOTSUPP;
1925 }
1926 #ifdef CONFIG_RTW_REPEATER_SON
1927 rtw_rson_do_disconnect(padapter);
1928 #endif
1929 return ret;
1930 }
1931
rtw_wx_set_scan(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * extra)1932 static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
1933 union iwreq_data *wrqu, char *extra)
1934 {
1935 u8 _status = _FALSE;
1936 int ret = 0;
1937 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1938 /*struct mlme_priv *pmlmepriv = &padapter->mlmepriv;*/
1939 struct sitesurvey_parm parm;
1940 u8 ssc_chk;
1941 #ifdef CONFIG_P2P
1942 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
1943 #endif /* CONFIG_P2P */
1944
1945 #ifdef DBG_IOCTL
1946 RTW_INFO("DBG_IOCTL %s:%d\n", __FUNCTION__, __LINE__);
1947 #endif
1948
1949 #if 1
1950 ssc_chk = rtw_sitesurvey_condition_check(padapter, _FALSE);
1951
1952 #ifdef CONFIG_DOSCAN_IN_BUSYTRAFFIC
1953 if ((ssc_chk != SS_ALLOW) && (ssc_chk != SS_DENY_BUSY_TRAFFIC))
1954 #else
1955 /* When Busy Traffic, driver do not site survey. So driver return success. */
1956 /* wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */
1957 /* modify by thomas 2011-02-22. */
1958 if (ssc_chk != SS_ALLOW)
1959 #endif
1960 {
1961 if (ssc_chk == SS_DENY_MP_MODE)
1962 ret = -EPERM;
1963 #ifdef DBG_LA_MODE
1964 else if (ssc_chk == SS_DENY_LA_MODE)
1965 ret = -EPERM;
1966 #endif
1967 else
1968 indicate_wx_scan_complete_event(padapter);
1969
1970 goto exit;
1971 } else
1972 RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
1973
1974 rtw_ps_deny(padapter, PS_DENY_SCAN);
1975 if (_FAIL == rtw_pwr_wakeup(padapter)) {
1976 ret = -1;
1977 goto cancel_ps_deny;
1978 }
1979 if (!rtw_is_adapter_up(padapter)) {
1980 ret = -1;
1981 goto cancel_ps_deny;
1982 }
1983 #else
1984
1985 #ifdef CONFIG_MP_INCLUDED
1986 if (rtw_mp_mode_check(padapter)) {
1987 RTW_INFO("MP mode block Scan request\n");
1988 ret = -EPERM;
1989 goto exit;
1990 }
1991 #endif
1992 if (rtw_is_scan_deny(padapter)) {
1993 indicate_wx_scan_complete_event(padapter);
1994 goto exit;
1995 }
1996
1997 rtw_ps_deny(padapter, PS_DENY_SCAN);
1998 if (_FAIL == rtw_pwr_wakeup(padapter)) {
1999 ret = -1;
2000 goto cancel_ps_deny;
2001 }
2002
2003 if (!rtw_is_adapter_up(padapter)) {
2004 ret = -1;
2005 goto cancel_ps_deny;
2006 }
2007
2008 #ifndef CONFIG_DOSCAN_IN_BUSYTRAFFIC
2009 /* When Busy Traffic, driver do not site survey. So driver return success. */
2010 /* wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */
2011 /* modify by thomas 2011-02-22. */
2012 if (rtw_mi_busy_traffic_check(padapter)) {
2013 indicate_wx_scan_complete_event(padapter);
2014 goto cancel_ps_deny;
2015 }
2016 #endif
2017 #ifdef CONFIG_RTW_REPEATER_SON
2018 if (padapter->rtw_rson_scanstage == RSON_SCAN_PROCESS) {
2019 RTW_INFO(FUNC_ADPT_FMT" blocking scan for under rson scanning process\n", FUNC_ADPT_ARG(padapter));
2020 indicate_wx_scan_complete_event(padapter);
2021 goto cancel_ps_deny;
2022 }
2023 #endif
2024 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) && check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
2025 RTW_INFO("AP mode process WPS\n");
2026 indicate_wx_scan_complete_event(padapter);
2027 goto cancel_ps_deny;
2028 }
2029
2030 if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY | WIFI_UNDER_LINKING) == _TRUE) {
2031 indicate_wx_scan_complete_event(padapter);
2032 goto cancel_ps_deny;
2033 }
2034
2035 #ifdef CONFIG_CONCURRENT_MODE
2036 if (rtw_mi_buddy_check_fwstate(padapter,
2037 WIFI_UNDER_SURVEY | WIFI_UNDER_LINKING | WIFI_UNDER_WPS)) {
2038
2039 indicate_wx_scan_complete_event(padapter);
2040 goto cancel_ps_deny;
2041 }
2042 #endif
2043 #endif
2044
2045 #ifdef CONFIG_P2P
2046 if (pwdinfo->p2p_state != P2P_STATE_NONE) {
2047 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
2048 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
2049 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_FULL);
2050 rtw_free_network_queue(padapter, _TRUE);
2051 }
2052 #endif /* CONFIG_P2P */
2053
2054 #if WIRELESS_EXT >= 17
2055 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
2056 struct iw_scan_req *req = (struct iw_scan_req *)extra;
2057
2058 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
2059 int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE);
2060
2061 rtw_init_sitesurvey_parm(padapter, &parm);
2062 _rtw_memcpy(&parm.ssid[0].Ssid, &req->essid, len);
2063 parm.ssid[0].SsidLength = len;
2064 parm.ssid_num = 1;
2065
2066 RTW_INFO("IW_SCAN_THIS_ESSID, ssid=%s, len=%d\n", req->essid, req->essid_len);
2067
2068 _status = rtw_set_802_11_bssid_list_scan(padapter, &parm);
2069
2070 } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE)
2071 RTW_INFO("rtw_wx_set_scan, req->scan_type == IW_SCAN_TYPE_PASSIVE\n");
2072
2073 } else
2074 #endif
2075
2076 if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE
2077 && _rtw_memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE) == _TRUE
2078 ) {
2079 int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE;
2080 char *pos = extra + WEXT_CSCAN_HEADER_SIZE;
2081 char section;
2082 char sec_len;
2083 int ssid_index = 0;
2084
2085 /* RTW_INFO("%s COMBO_SCAN header is recognized\n", __FUNCTION__); */
2086 rtw_init_sitesurvey_parm(padapter, &parm);
2087
2088 while (len >= 1) {
2089 section = *(pos++);
2090 len -= 1;
2091
2092 switch (section) {
2093 case WEXT_CSCAN_SSID_SECTION:
2094 /* RTW_INFO("WEXT_CSCAN_SSID_SECTION\n"); */
2095 if (len < 1) {
2096 len = 0;
2097 break;
2098 }
2099
2100 sec_len = *(pos++);
2101 len -= 1;
2102
2103 if (sec_len > 0 && sec_len <= len) {
2104
2105 parm.ssid[ssid_index].SsidLength = sec_len;
2106 _rtw_memcpy(&parm.ssid[ssid_index].Ssid, pos, sec_len);
2107
2108 /* RTW_INFO("%s COMBO_SCAN with specific parm.ssid:%s, %d\n", __FUNCTION__ */
2109 /* , parm.ssid[ssid_index].Ssid, parm.ssid[ssid_index].SsidLength); */
2110 ssid_index++;
2111 }
2112
2113 pos += sec_len;
2114 len -= sec_len;
2115 break;
2116
2117
2118 case WEXT_CSCAN_CHANNEL_SECTION:
2119 /* RTW_INFO("WEXT_CSCAN_CHANNEL_SECTION\n"); */
2120 pos += 1;
2121 len -= 1;
2122 break;
2123 case WEXT_CSCAN_ACTV_DWELL_SECTION:
2124 /* RTW_INFO("WEXT_CSCAN_ACTV_DWELL_SECTION\n"); */
2125 pos += 2;
2126 len -= 2;
2127 break;
2128 case WEXT_CSCAN_PASV_DWELL_SECTION:
2129 /* RTW_INFO("WEXT_CSCAN_PASV_DWELL_SECTION\n"); */
2130 pos += 2;
2131 len -= 2;
2132 break;
2133 case WEXT_CSCAN_HOME_DWELL_SECTION:
2134 /* RTW_INFO("WEXT_CSCAN_HOME_DWELL_SECTION\n"); */
2135 pos += 2;
2136 len -= 2;
2137 break;
2138 case WEXT_CSCAN_TYPE_SECTION:
2139 /* RTW_INFO("WEXT_CSCAN_TYPE_SECTION\n"); */
2140 pos += 1;
2141 len -= 1;
2142 break;
2143 #if 0
2144 case WEXT_CSCAN_NPROBE_SECTION:
2145 RTW_INFO("WEXT_CSCAN_NPROBE_SECTION\n");
2146 break;
2147 #endif
2148
2149 default:
2150 /* RTW_INFO("Unknown CSCAN section %c\n", section); */
2151 len = 0; /* stop parsing */
2152 }
2153 /* RTW_INFO("len:%d\n", len); */
2154
2155 }
2156 parm.ssid_num = ssid_index;
2157
2158 /* jeff: it has still some scan paramater to parse, we only do this now... */
2159 _status = rtw_set_802_11_bssid_list_scan(padapter, &parm);
2160
2161 } else
2162
2163 _status = rtw_set_802_11_bssid_list_scan(padapter, NULL);
2164
2165 if (_status == _FALSE)
2166 ret = -1;
2167
2168 cancel_ps_deny:
2169 rtw_ps_deny_cancel(padapter, PS_DENY_SCAN);
2170
2171 exit:
2172 #ifdef DBG_IOCTL
2173 RTW_INFO("DBG_IOCTL %s:%d return %d\n", __FUNCTION__, __LINE__, ret);
2174 #endif
2175
2176 return ret;
2177 }
2178
rtw_wx_get_scan(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * extra)2179 static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
2180 union iwreq_data *wrqu, char *extra)
2181 {
2182 _irqL irqL;
2183 _list *plist, *phead;
2184 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2185 struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
2186 RT_CHANNEL_INFO *chset = rfctl->channel_set;
2187 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2188 _queue *queue = &(pmlmepriv->scanned_queue);
2189 struct wlan_network *pnetwork = NULL;
2190 char *ev = extra;
2191 char *stop = ev + wrqu->data.length;
2192 u32 ret = 0;
2193 u32 wait_for_surveydone;
2194 sint wait_status;
2195 u8 ch;
2196
2197 #ifdef CONFIG_P2P
2198 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2199 #endif /* CONFIG_P2P */
2200
2201
2202 #ifdef DBG_IOCTL
2203 RTW_INFO("DBG_IOCTL %s:%d\n", __FUNCTION__, __LINE__);
2204 #endif
2205
2206 if (adapter_to_pwrctl(padapter)->brfoffbyhw && rtw_is_drv_stopped(padapter)) {
2207 ret = -EINVAL;
2208 goto exit;
2209 }
2210
2211 #ifdef CONFIG_P2P
2212 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
2213 wait_for_surveydone = 200;
2214 else {
2215 /* P2P is disabled */
2216 wait_for_surveydone = 100;
2217 }
2218 #else
2219 {
2220 wait_for_surveydone = 100;
2221 }
2222 #endif /* CONFIG_P2P */
2223
2224 #if 1 /* Wireless Extension use EAGAIN to try */
2225 wait_status = WIFI_UNDER_SURVEY
2226 #ifndef CONFIG_RTW_ANDROID
2227 | WIFI_UNDER_LINKING
2228 #endif
2229 ;
2230
2231 while (check_fwstate(pmlmepriv, wait_status) == _TRUE)
2232 return -EAGAIN;
2233 #else
2234 wait_status = WIFI_UNDER_SURVEY
2235 #ifndef CONFIG_RTW_ANDROID
2236 | WIFI_UNDER_LINKING
2237 #endif
2238 ;
2239
2240 while (check_fwstate(pmlmepriv, wait_status) == _TRUE) {
2241 rtw_msleep_os(30);
2242 cnt++;
2243 if (cnt > wait_for_surveydone)
2244 break;
2245 }
2246 #endif
2247 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
2248
2249 phead = get_list_head(queue);
2250 plist = get_next(phead);
2251
2252 while (1) {
2253 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
2254 break;
2255
2256 if ((stop - ev) < SCAN_ITEM_SIZE) {
2257 if(wrqu->data.length == MAX_SCAN_BUFFER_LEN){ /*max buffer len defined by iwlist*/
2258 ret = 0;
2259 RTW_INFO("%s: Scan results incomplete\n", __FUNCTION__);
2260 break;
2261 }
2262 ret = -E2BIG;
2263 break;
2264 }
2265
2266 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
2267 ch = pnetwork->network.Configuration.DSConfig;
2268
2269 /* report network only if the current channel set contains the channel to which this network belongs */
2270 if (rtw_chset_search_ch(chset, ch) >= 0
2271 && rtw_mlme_band_check(padapter, ch) == _TRUE
2272 && _TRUE == rtw_validate_ssid(&(pnetwork->network.Ssid))
2273 && (!IS_DFS_SLAVE_WITH_RD(rfctl)
2274 || rtw_rfctl_dfs_domain_unknown(rfctl)
2275 || !rtw_chset_is_ch_non_ocp(chset, ch))
2276 )
2277 ev = translate_scan(padapter, a, pnetwork, ev, stop);
2278
2279 plist = get_next(plist);
2280
2281 }
2282
2283 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
2284
2285 wrqu->data.length = ev - extra;
2286 wrqu->data.flags = 0;
2287
2288 exit:
2289
2290
2291 #ifdef DBG_IOCTL
2292 RTW_INFO("DBG_IOCTL %s:%d return %d\n", __FUNCTION__, __LINE__, ret);
2293 #endif
2294
2295 return ret ;
2296
2297 }
2298
2299 /* set ssid flow
2300 * s1. rtw_set_802_11_infrastructure_mode()
2301 * s2. set_802_11_authenticaion_mode()
2302 * s3. set_802_11_encryption_mode()
2303 * 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)2304 static int rtw_wx_set_essid(struct net_device *dev,
2305 struct iw_request_info *a,
2306 union iwreq_data *wrqu, char *extra)
2307 {
2308 _irqL irqL;
2309 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2310 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2311 _queue *queue = &pmlmepriv->scanned_queue;
2312 _list *phead;
2313 struct wlan_network *pnetwork = NULL;
2314 NDIS_802_11_AUTHENTICATION_MODE authmode;
2315 NDIS_802_11_SSID ndis_ssid;
2316 u8 *dst_ssid, *src_ssid;
2317
2318 uint ret = 0, len;
2319
2320
2321 #ifdef DBG_IOCTL
2322 RTW_INFO("DBG_IOCTL %s:%d\n", __FUNCTION__, __LINE__);
2323 #endif
2324 #ifdef CONFIG_WEXT_DONT_JOIN_BYSSID
2325 RTW_INFO("%s: CONFIG_WEXT_DONT_JOIN_BYSSID be defined!! only allow bssid joining\n", __func__);
2326 return -EPERM;
2327 #endif
2328
2329 #if WIRELESS_EXT <= 20
2330 if ((wrqu->essid.length - 1) > IW_ESSID_MAX_SIZE) {
2331 #else
2332 if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
2333 #endif
2334 ret = -E2BIG;
2335 goto exit;
2336 }
2337
2338
2339
2340 rtw_ps_deny(padapter, PS_DENY_JOIN);
2341 if (_FAIL == rtw_pwr_wakeup(padapter)) {
2342 ret = -1;
2343 goto cancel_ps_deny;
2344 }
2345
2346 if (!padapter->bup) {
2347 ret = -1;
2348 goto cancel_ps_deny;
2349 }
2350
2351 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
2352 ret = -1;
2353 goto cancel_ps_deny;
2354 }
2355
2356 #ifdef CONFIG_CONCURRENT_MODE
2357 if (rtw_mi_buddy_check_fwstate(padapter, WIFI_UNDER_SURVEY | WIFI_UNDER_LINKING)) {
2358 RTW_INFO("set ssid, but buddy_intf is under scanning or linking\n");
2359 ret = -EINVAL;
2360 goto cancel_ps_deny;
2361 }
2362 #endif
2363 authmode = padapter->securitypriv.ndisauthtype;
2364 RTW_INFO("=>%s\n", __FUNCTION__);
2365 if (wrqu->essid.flags && wrqu->essid.length) {
2366 /* Commented by Albert 20100519 */
2367 /* We got the codes in "set_info" function of iwconfig source code. */
2368 /* ========================================= */
2369 /* wrq.u.essid.length = strlen(essid) + 1; */
2370 /* if(we_kernel_version > 20) */
2371 /* wrq.u.essid.length--; */
2372 /* ========================================= */
2373 /* That means, if the WIRELESS_EXT less than or equal to 20, the correct ssid len should subtract 1. */
2374 #if WIRELESS_EXT <= 20
2375 len = ((wrqu->essid.length - 1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length - 1) : IW_ESSID_MAX_SIZE;
2376 #else
2377 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
2378 #endif
2379
2380 if (wrqu->essid.length != 33)
2381 RTW_INFO("ssid=%s, len=%d\n", extra, wrqu->essid.length);
2382
2383 _rtw_memset(&ndis_ssid, 0, sizeof(NDIS_802_11_SSID));
2384 ndis_ssid.SsidLength = len;
2385 _rtw_memcpy(ndis_ssid.Ssid, extra, len);
2386 src_ssid = ndis_ssid.Ssid;
2387
2388 _enter_critical_bh(&queue->lock, &irqL);
2389 phead = get_list_head(queue);
2390 pmlmepriv->pscanned = get_next(phead);
2391
2392 while (1) {
2393 if (rtw_end_of_queue_search(phead, pmlmepriv->pscanned) == _TRUE) {
2394 #if 0
2395 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE) {
2396 rtw_set_802_11_ssid(padapter, &ndis_ssid);
2397
2398 goto cancel_ps_deny;
2399 } else {
2400 ret = -EINVAL;
2401 goto cancel_ps_deny;
2402 }
2403 #endif
2404
2405 break;
2406 }
2407
2408 pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
2409
2410 pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
2411
2412 dst_ssid = pnetwork->network.Ssid.Ssid;
2413
2414
2415 if ((_rtw_memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength) == _TRUE) &&
2416 (pnetwork->network.Ssid.SsidLength == ndis_ssid.SsidLength)) {
2417
2418 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE) {
2419 if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
2420 continue;
2421 }
2422
2423 if (rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode, 0) == _FALSE) {
2424 ret = -1;
2425 _exit_critical_bh(&queue->lock, &irqL);
2426 goto cancel_ps_deny;
2427 }
2428
2429 break;
2430 }
2431 }
2432 _exit_critical_bh(&queue->lock, &irqL);
2433 rtw_set_802_11_authentication_mode(padapter, authmode);
2434 /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
2435 if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == _FALSE) {
2436 ret = -1;
2437 goto cancel_ps_deny;
2438 }
2439 }
2440
2441 cancel_ps_deny:
2442 rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
2443
2444 exit:
2445 RTW_INFO("<=%s, ret %d\n", __FUNCTION__, ret);
2446
2447 #ifdef DBG_IOCTL
2448 RTW_INFO("DBG_IOCTL %s:%d return %d\n", __FUNCTION__, __LINE__, ret);
2449 #endif
2450
2451
2452 return ret;
2453 }
2454
2455 static int rtw_wx_get_essid(struct net_device *dev,
2456 struct iw_request_info *a,
2457 union iwreq_data *wrqu, char *extra)
2458 {
2459 u32 len, ret = 0;
2460 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2461 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2462 WLAN_BSSID_EX *pcur_bss = &pmlmepriv->cur_network.network;
2463
2464
2465
2466 if ((check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE) ||
2467 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)) {
2468 len = pcur_bss->Ssid.SsidLength;
2469
2470 wrqu->essid.length = len;
2471
2472 _rtw_memcpy(extra, pcur_bss->Ssid.Ssid, len);
2473
2474 wrqu->essid.flags = 1;
2475 } else {
2476 ret = -1;
2477 goto exit;
2478 }
2479
2480 exit:
2481
2482
2483 return ret;
2484
2485 }
2486
2487 static int rtw_wx_set_rate(struct net_device *dev,
2488 struct iw_request_info *a,
2489 union iwreq_data *wrqu, char *extra)
2490 {
2491 int ret = 0;
2492 #if 0
2493 int i;
2494 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2495 u8 datarates[NumRates];
2496 u32 target_rate = wrqu->bitrate.value;
2497 u32 fixed = wrqu->bitrate.fixed;
2498 u32 ratevalue = 0;
2499 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
2500
2501
2502
2503 if (target_rate == -1) {
2504 ratevalue = 11;
2505 goto set_rate;
2506 }
2507 target_rate = target_rate / 100000;
2508
2509 switch (target_rate) {
2510 case 10:
2511 ratevalue = 0;
2512 break;
2513 case 20:
2514 ratevalue = 1;
2515 break;
2516 case 55:
2517 ratevalue = 2;
2518 break;
2519 case 60:
2520 ratevalue = 3;
2521 break;
2522 case 90:
2523 ratevalue = 4;
2524 break;
2525 case 110:
2526 ratevalue = 5;
2527 break;
2528 case 120:
2529 ratevalue = 6;
2530 break;
2531 case 180:
2532 ratevalue = 7;
2533 break;
2534 case 240:
2535 ratevalue = 8;
2536 break;
2537 case 360:
2538 ratevalue = 9;
2539 break;
2540 case 480:
2541 ratevalue = 10;
2542 break;
2543 case 540:
2544 ratevalue = 11;
2545 break;
2546 default:
2547 ratevalue = 11;
2548 break;
2549 }
2550
2551 set_rate:
2552
2553 for (i = 0; i < NumRates; i++) {
2554 if (ratevalue == mpdatarate[i]) {
2555 datarates[i] = mpdatarate[i];
2556 if (fixed == 0)
2557 break;
2558 } else
2559 datarates[i] = 0xff;
2560
2561 }
2562
2563 if (rtw_setdatarate_cmd(padapter, datarates) != _SUCCESS) {
2564 ret = -1;
2565 }
2566
2567 #endif
2568 return ret;
2569 }
2570
2571 static int rtw_wx_get_rate(struct net_device *dev,
2572 struct iw_request_info *info,
2573 union iwreq_data *wrqu, char *extra)
2574 {
2575 u16 max_rate = 0;
2576
2577 max_rate = rtw_get_cur_max_rate((_adapter *)rtw_netdev_priv(dev));
2578
2579 if (max_rate == 0)
2580 return -EPERM;
2581
2582 wrqu->bitrate.fixed = 0; /* no auto select */
2583 wrqu->bitrate.value = max_rate * 100000;
2584
2585 return 0;
2586 }
2587
2588 static int rtw_wx_set_rts(struct net_device *dev,
2589 struct iw_request_info *info,
2590 union iwreq_data *wrqu, char *extra)
2591 {
2592 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2593
2594
2595 if (wrqu->rts.disabled)
2596 padapter->registrypriv.rts_thresh = 2347;
2597 else {
2598 if (wrqu->rts.value < 0 ||
2599 wrqu->rts.value > 2347)
2600 return -EINVAL;
2601
2602 padapter->registrypriv.rts_thresh = wrqu->rts.value;
2603 }
2604
2605 RTW_INFO("%s, rts_thresh=%d\n", __func__, padapter->registrypriv.rts_thresh);
2606
2607
2608 return 0;
2609
2610 }
2611
2612 static int rtw_wx_get_rts(struct net_device *dev,
2613 struct iw_request_info *info,
2614 union iwreq_data *wrqu, char *extra)
2615 {
2616 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2617
2618
2619 RTW_INFO("%s, rts_thresh=%d\n", __func__, padapter->registrypriv.rts_thresh);
2620
2621 wrqu->rts.value = padapter->registrypriv.rts_thresh;
2622 wrqu->rts.fixed = 0; /* no auto select */
2623 /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
2624
2625
2626 return 0;
2627 }
2628
2629 static int rtw_wx_set_frag(struct net_device *dev,
2630 struct iw_request_info *info,
2631 union iwreq_data *wrqu, char *extra)
2632 {
2633 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2634
2635
2636 if (wrqu->frag.disabled)
2637 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
2638 else {
2639 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
2640 wrqu->frag.value > MAX_FRAG_THRESHOLD)
2641 return -EINVAL;
2642
2643 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
2644 }
2645
2646 RTW_INFO("%s, frag_len=%d\n", __func__, padapter->xmitpriv.frag_len);
2647
2648
2649 return 0;
2650
2651 }
2652
2653 static int rtw_wx_get_frag(struct net_device *dev,
2654 struct iw_request_info *info,
2655 union iwreq_data *wrqu, char *extra)
2656 {
2657 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2658
2659
2660 RTW_INFO("%s, frag_len=%d\n", __func__, padapter->xmitpriv.frag_len);
2661
2662 wrqu->frag.value = padapter->xmitpriv.frag_len;
2663 wrqu->frag.fixed = 0; /* no auto select */
2664 /* wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); */
2665
2666
2667 return 0;
2668 }
2669
2670 static int rtw_wx_get_retry(struct net_device *dev,
2671 struct iw_request_info *info,
2672 union iwreq_data *wrqu, char *extra)
2673 {
2674 /* _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); */
2675
2676
2677 wrqu->retry.value = 7;
2678 wrqu->retry.fixed = 0; /* no auto select */
2679 wrqu->retry.disabled = 1;
2680
2681 return 0;
2682
2683 }
2684
2685 #if 0
2686 #define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */
2687 #define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */
2688 #define IW_ENCODE_MODE 0xF000 /* Modes defined below */
2689 #define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */
2690 #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */
2691 #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */
2692 #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */
2693 #define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
2694 #define IW_ENCODE_TEMP 0x0400 /* Temporary key */
2695 /*
2696 iwconfig wlan0 key on->flags = 0x6001->maybe it means auto
2697 iwconfig wlan0 key off->flags = 0x8800
2698 iwconfig wlan0 key open->flags = 0x2800
2699 iwconfig wlan0 key open 1234567890->flags = 0x2000
2700 iwconfig wlan0 key restricted->flags = 0x4800
2701 iwconfig wlan0 key open [3] 1234567890->flags = 0x2003
2702 iwconfig wlan0 key restricted [2] 1234567890->flags = 0x4002
2703 iwconfig wlan0 key open [3] -> flags = 0x2803
2704 iwconfig wlan0 key restricted [2] -> flags = 0x4802
2705 */
2706 #endif
2707
2708 static int rtw_wx_set_enc(struct net_device *dev,
2709 struct iw_request_info *info,
2710 union iwreq_data *wrqu, char *keybuf)
2711 {
2712 u32 key, ret = 0;
2713 u32 keyindex_provided;
2714 NDIS_802_11_WEP wep;
2715 NDIS_802_11_AUTHENTICATION_MODE authmode;
2716
2717 struct iw_point *erq = &(wrqu->encoding);
2718 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2719 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
2720 RTW_INFO("+rtw_wx_set_enc, flags=0x%x\n", erq->flags);
2721
2722 _rtw_memset(&wep, 0, sizeof(NDIS_802_11_WEP));
2723
2724 key = erq->flags & IW_ENCODE_INDEX;
2725
2726
2727 if (erq->flags & IW_ENCODE_DISABLED) {
2728 RTW_INFO("EncryptionDisabled\n");
2729 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
2730 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
2731 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
2732 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
2733 authmode = Ndis802_11AuthModeOpen;
2734 padapter->securitypriv.ndisauthtype = authmode;
2735
2736 goto exit;
2737 }
2738
2739 if (key) {
2740 if (key > WEP_KEYS)
2741 return -EINVAL;
2742 key--;
2743 keyindex_provided = 1;
2744 } else {
2745 keyindex_provided = 0;
2746 key = padapter->securitypriv.dot11PrivacyKeyIndex;
2747 RTW_INFO("rtw_wx_set_enc, key=%d\n", key);
2748 }
2749
2750 /* set authentication mode */
2751 if (erq->flags & IW_ENCODE_OPEN) {
2752 RTW_INFO("rtw_wx_set_enc():IW_ENCODE_OPEN\n");
2753 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
2754
2755 #ifdef CONFIG_PLATFORM_MT53XX
2756 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
2757 #else
2758 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
2759 #endif
2760
2761 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
2762 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
2763 authmode = Ndis802_11AuthModeOpen;
2764 padapter->securitypriv.ndisauthtype = authmode;
2765 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
2766 RTW_INFO("rtw_wx_set_enc():IW_ENCODE_RESTRICTED\n");
2767 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
2768
2769 #ifdef CONFIG_PLATFORM_MT53XX
2770 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
2771 #else
2772 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
2773 #endif
2774
2775 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
2776 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
2777 authmode = Ndis802_11AuthModeShared;
2778 padapter->securitypriv.ndisauthtype = authmode;
2779 } else {
2780 RTW_INFO("rtw_wx_set_enc():erq->flags=0x%x\n", erq->flags);
2781
2782 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
2783 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
2784 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
2785 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
2786 authmode = Ndis802_11AuthModeOpen;
2787 padapter->securitypriv.ndisauthtype = authmode;
2788 }
2789
2790 wep.KeyIndex = key;
2791 if (erq->length > 0) {
2792 wep.KeyLength = erq->length <= 5 ? 5 : 13;
2793
2794 wep.Length = wep.KeyLength + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
2795 } else {
2796 wep.KeyLength = 0 ;
2797
2798 if (keyindex_provided == 1) { /* set key_id only, no given KeyMaterial(erq->length==0). */
2799 padapter->securitypriv.dot11PrivacyKeyIndex = key;
2800
2801 RTW_INFO("(keyindex_provided == 1), keyid=%d, key_len=%d\n", key, padapter->securitypriv.dot11DefKeylen[key]);
2802
2803 switch (padapter->securitypriv.dot11DefKeylen[key]) {
2804 case 5:
2805 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
2806 break;
2807 case 13:
2808 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
2809 break;
2810 default:
2811 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
2812 break;
2813 }
2814
2815 goto exit;
2816
2817 }
2818
2819 }
2820
2821 wep.KeyIndex |= 0x80000000;
2822
2823 _rtw_memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
2824
2825 if (rtw_set_802_11_add_wep(padapter, &wep) == _FALSE) {
2826 if (rf_on == pwrpriv->rf_pwrstate)
2827 ret = -EOPNOTSUPP;
2828 goto exit;
2829 }
2830
2831 exit:
2832
2833
2834 return ret;
2835
2836 }
2837
2838 static int rtw_wx_get_enc(struct net_device *dev,
2839 struct iw_request_info *info,
2840 union iwreq_data *wrqu, char *keybuf)
2841 {
2842 uint key, ret = 0;
2843 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2844 struct iw_point *erq = &(wrqu->encoding);
2845 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2846
2847
2848 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) != _TRUE) {
2849 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != _TRUE) {
2850 erq->length = 0;
2851 erq->flags |= IW_ENCODE_DISABLED;
2852 return 0;
2853 }
2854 }
2855
2856
2857 key = erq->flags & IW_ENCODE_INDEX;
2858
2859 if (key) {
2860 if (key > WEP_KEYS)
2861 return -EINVAL;
2862 key--;
2863 } else
2864 key = padapter->securitypriv.dot11PrivacyKeyIndex;
2865
2866 erq->flags = key + 1;
2867
2868 /* if(padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen) */
2869 /* { */
2870 /* erq->flags |= IW_ENCODE_OPEN; */
2871 /* } */
2872
2873 switch (padapter->securitypriv.ndisencryptstatus) {
2874 case Ndis802_11EncryptionNotSupported:
2875 case Ndis802_11EncryptionDisabled:
2876
2877 erq->length = 0;
2878 erq->flags |= IW_ENCODE_DISABLED;
2879
2880 break;
2881
2882 case Ndis802_11Encryption1Enabled:
2883
2884 erq->length = padapter->securitypriv.dot11DefKeylen[key];
2885
2886 if (erq->length) {
2887 _rtw_memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
2888
2889 erq->flags |= IW_ENCODE_ENABLED;
2890
2891 if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
2892 erq->flags |= IW_ENCODE_OPEN;
2893 else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
2894 erq->flags |= IW_ENCODE_RESTRICTED;
2895 } else {
2896 erq->length = 0;
2897 erq->flags |= IW_ENCODE_DISABLED;
2898 }
2899
2900 break;
2901
2902 case Ndis802_11Encryption2Enabled:
2903 case Ndis802_11Encryption3Enabled:
2904
2905 erq->length = 16;
2906 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
2907
2908 break;
2909
2910 default:
2911 erq->length = 0;
2912 erq->flags |= IW_ENCODE_DISABLED;
2913
2914 break;
2915
2916 }
2917
2918
2919 return ret;
2920
2921 }
2922
2923 static int rtw_wx_get_power(struct net_device *dev,
2924 struct iw_request_info *info,
2925 union iwreq_data *wrqu, char *extra)
2926 {
2927 /* _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); */
2928
2929 wrqu->power.value = 0;
2930 wrqu->power.fixed = 0; /* no auto select */
2931 wrqu->power.disabled = 1;
2932
2933 return 0;
2934
2935 }
2936
2937 static int rtw_wx_set_gen_ie(struct net_device *dev,
2938 struct iw_request_info *info,
2939 union iwreq_data *wrqu, char *extra)
2940 {
2941 int ret;
2942 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2943
2944 ret = rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
2945
2946 return ret;
2947 }
2948
2949 static int rtw_wx_set_auth(struct net_device *dev,
2950 struct iw_request_info *info,
2951 union iwreq_data *wrqu, char *extra)
2952 {
2953 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
2954 struct iw_param *param = (struct iw_param *)&(wrqu->param);
2955 #ifdef CONFIG_WAPI_SUPPORT
2956 #ifndef CONFIG_IOCTL_CFG80211
2957 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2958 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2959 struct security_priv *psecuritypriv = &padapter->securitypriv;
2960 u32 value = param->value;
2961 #endif
2962 #endif
2963 int ret = 0;
2964
2965 switch (param->flags & IW_AUTH_INDEX) {
2966
2967 case IW_AUTH_WPA_VERSION:
2968 #ifdef CONFIG_WAPI_SUPPORT
2969 #ifndef CONFIG_IOCTL_CFG80211
2970 padapter->wapiInfo.bWapiEnable = false;
2971 if (value == IW_AUTH_WAPI_VERSION_1) {
2972 padapter->wapiInfo.bWapiEnable = true;
2973 psecuritypriv->dot11PrivacyAlgrthm = _SMS4_;
2974 psecuritypriv->dot118021XGrpPrivacy = _SMS4_;
2975 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_WAPI;
2976 pmlmeinfo->auth_algo = psecuritypriv->dot11AuthAlgrthm;
2977 padapter->wapiInfo.extra_prefix_len = WAPI_EXT_LEN;
2978 padapter->wapiInfo.extra_postfix_len = SMS4_MIC_LEN;
2979 }
2980 #endif
2981 #endif
2982 break;
2983 case IW_AUTH_CIPHER_PAIRWISE:
2984
2985 break;
2986 case IW_AUTH_CIPHER_GROUP:
2987
2988 break;
2989 case IW_AUTH_KEY_MGMT:
2990 #ifdef CONFIG_WAPI_SUPPORT
2991 #ifndef CONFIG_IOCTL_CFG80211
2992 RTW_INFO("rtw_wx_set_auth: IW_AUTH_KEY_MGMT case\n");
2993 if (value == IW_AUTH_KEY_MGMT_WAPI_PSK)
2994 padapter->wapiInfo.bWapiPSK = true;
2995 else
2996 padapter->wapiInfo.bWapiPSK = false;
2997 RTW_INFO("rtw_wx_set_auth: IW_AUTH_KEY_MGMT bwapipsk %d\n", padapter->wapiInfo.bWapiPSK);
2998 #endif
2999 #endif
3000 /*
3001 * ??? does not use these parameters
3002 */
3003 break;
3004
3005 case IW_AUTH_TKIP_COUNTERMEASURES: {
3006 if (param->value) {
3007 /* wpa_supplicant is enabling the tkip countermeasure. */
3008 padapter->securitypriv.btkip_countermeasure = _TRUE;
3009 } else {
3010 /* wpa_supplicant is disabling the tkip countermeasure. */
3011 padapter->securitypriv.btkip_countermeasure = _FALSE;
3012 }
3013 break;
3014 }
3015 case IW_AUTH_DROP_UNENCRYPTED: {
3016 /* HACK:
3017 *
3018 * wpa_supplicant calls set_wpa_enabled when the driver
3019 * is loaded and unloaded, regardless of if WPA is being
3020 * used. No other calls are made which can be used to
3021 * determine if encryption will be used or not prior to
3022 * association being expected. If encryption is not being
3023 * used, drop_unencrypted is set to false, else true -- we
3024 * can use this to determine if the CAP_PRIVACY_ON bit should
3025 * be set.
3026 */
3027
3028 if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled) {
3029 break;/* it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled, */
3030 /* then it needn't reset it; */
3031 }
3032
3033 if (param->value) {
3034 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
3035 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
3036 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
3037 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
3038 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
3039 }
3040
3041 break;
3042 }
3043
3044 case IW_AUTH_80211_AUTH_ALG:
3045
3046 #if defined(CONFIG_RTW_ANDROID) || 1
3047 /*
3048 * It's the starting point of a link layer connection using wpa_supplicant
3049 */
3050 if (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE)) {
3051 LeaveAllPowerSaveMode(padapter);
3052 rtw_disassoc_cmd(padapter, 500, RTW_CMDF_WAIT_ACK);
3053 RTW_INFO("%s...call rtw_indicate_disconnect\n ", __FUNCTION__);
3054 rtw_indicate_disconnect(padapter, 0, _FALSE);
3055 rtw_free_assoc_resources_cmd(padapter, _TRUE, RTW_CMDF_WAIT_ACK);
3056 }
3057 #endif
3058
3059
3060 ret = wpa_set_auth_algs(dev, (u32)param->value);
3061
3062 break;
3063
3064 case IW_AUTH_WPA_ENABLED:
3065
3066 /* if(param->value) */
3067 /* padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; */ /* 802.1x */
3068 /* else */
3069 /* padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; */ /* open system */
3070
3071 /* _disassociate(priv); */
3072
3073 break;
3074
3075 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
3076 /* ieee->ieee802_1x = param->value; */
3077 break;
3078
3079 case IW_AUTH_PRIVACY_INVOKED:
3080 /* ieee->privacy_invoked = param->value; */
3081 break;
3082
3083 #ifdef CONFIG_WAPI_SUPPORT
3084 #ifndef CONFIG_IOCTL_CFG80211
3085 case IW_AUTH_WAPI_ENABLED:
3086 break;
3087 #endif
3088 #endif
3089
3090 default:
3091 return -EOPNOTSUPP;
3092
3093 }
3094
3095 return ret;
3096
3097 }
3098
3099 static int rtw_wx_set_enc_ext(struct net_device *dev,
3100 struct iw_request_info *info,
3101 union iwreq_data *wrqu, char *extra)
3102 {
3103 char *alg_name;
3104 u32 param_len;
3105 struct ieee_param *param = NULL;
3106 struct iw_point *pencoding = &wrqu->encoding;
3107 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
3108 int ret = 0;
3109
3110 param_len = sizeof(struct ieee_param) + pext->key_len;
3111 param = (struct ieee_param *)rtw_malloc(param_len);
3112 if (param == NULL)
3113 return -1;
3114
3115 _rtw_memset(param, 0, param_len);
3116
3117 param->cmd = IEEE_CMD_SET_ENCRYPTION;
3118 _rtw_memset(param->sta_addr, 0xff, ETH_ALEN);
3119
3120
3121 switch (pext->alg) {
3122 case IW_ENCODE_ALG_NONE:
3123 /* todo: remove key */
3124 /* remove = 1; */
3125 alg_name = "none";
3126 break;
3127 case IW_ENCODE_ALG_WEP:
3128 alg_name = "WEP";
3129 break;
3130 case IW_ENCODE_ALG_TKIP:
3131 alg_name = "TKIP";
3132 break;
3133 case IW_ENCODE_ALG_CCMP:
3134 alg_name = "CCMP";
3135 break;
3136 #ifdef CONFIG_IEEE80211W
3137 case IW_ENCODE_ALG_AES_CMAC:
3138 alg_name = "BIP";
3139 break;
3140 #endif /* CONFIG_IEEE80211W */
3141 #ifdef CONFIG_WAPI_SUPPORT
3142 #ifndef CONFIG_IOCTL_CFG80211
3143 case IW_ENCODE_ALG_SM4:
3144 alg_name = "SMS4";
3145 _rtw_memcpy(param->sta_addr, pext->addr.sa_data, ETH_ALEN);
3146 RTW_INFO("rtw_wx_set_enc_ext: SMS4 case\n");
3147 break;
3148 #endif
3149 #endif
3150 default:
3151 ret = -1;
3152 goto exit;
3153 }
3154
3155 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
3156
3157 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
3158 param->u.crypt.set_tx = 1;
3159
3160 /* cliW: WEP does not have group key
3161 * just not checking GROUP key setting
3162 */
3163 if ((pext->alg != IW_ENCODE_ALG_WEP) &&
3164 ((pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
3165 #ifdef CONFIG_IEEE80211W
3166 || (pext->ext_flags & IW_ENCODE_ALG_AES_CMAC)
3167 #endif /* CONFIG_IEEE80211W */
3168 ))
3169 param->u.crypt.set_tx = 0;
3170
3171 param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1 ;
3172
3173 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
3174 #ifdef CONFIG_WAPI_SUPPORT
3175 #ifndef CONFIG_IOCTL_CFG80211
3176 if (pext->alg == IW_ENCODE_ALG_SM4)
3177 _rtw_memcpy(param->u.crypt.seq, pext->rx_seq, 16);
3178 else
3179 #endif /* CONFIG_IOCTL_CFG80211 */
3180 #endif /* CONFIG_WAPI_SUPPORT */
3181 _rtw_memcpy(param->u.crypt.seq, pext->rx_seq, 8);
3182 }
3183
3184 if (pext->key_len) {
3185 param->u.crypt.key_len = pext->key_len;
3186 /* _rtw_memcpy(param + 1, pext + 1, pext->key_len); */
3187 _rtw_memcpy(param->u.crypt.key, pext + 1, pext->key_len);
3188 }
3189
3190 if (pencoding->flags & IW_ENCODE_DISABLED) {
3191 /* todo: remove key */
3192 /* remove = 1; */
3193 }
3194
3195 ret = wpa_set_encryption(dev, param, param_len);
3196
3197 exit:
3198 if (param)
3199 rtw_mfree((u8 *)param, param_len);
3200
3201 return ret;
3202 }
3203
3204
3205 static int rtw_wx_get_nick(struct net_device *dev,
3206 struct iw_request_info *info,
3207 union iwreq_data *wrqu, char *extra)
3208 {
3209 /* _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); */
3210 /* struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); */
3211 /* struct security_priv *psecuritypriv = &padapter->securitypriv; */
3212
3213 if (extra) {
3214 wrqu->data.length = 14;
3215 wrqu->data.flags = 1;
3216 _rtw_memcpy(extra, "<WIFI@REALTEK>", 14);
3217 }
3218
3219 /* rtw_signal_process(pid, SIGUSR1); */ /* for test */
3220
3221 /* dump debug info here */
3222 #if 0
3223 u32 dot11AuthAlgrthm; /* 802.11 auth, could be open, shared, and 8021x */
3224 u32 dot11PrivacyAlgrthm; /* This specify the privacy for shared auth. algorithm. */
3225 u32 dot118021XGrpPrivacy; /* This specify the privacy algthm. used for Grp key */
3226 u32 ndisauthtype;
3227 u32 ndisencryptstatus;
3228 #endif
3229
3230 /* RTW_INFO("auth_alg=0x%x, enc_alg=0x%x, auth_type=0x%x, enc_type=0x%x\n", */
3231 /* psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm, */
3232 /* psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus); */
3233
3234 /* RTW_INFO("enc_alg=0x%x\n", psecuritypriv->dot11PrivacyAlgrthm); */
3235 /* RTW_INFO("auth_type=0x%x\n", psecuritypriv->ndisauthtype); */
3236 /* RTW_INFO("enc_type=0x%x\n", psecuritypriv->ndisencryptstatus); */
3237
3238 #if 0
3239 RTW_INFO("dbg(0x210)=0x%x\n", rtw_read32(padapter, 0x210));
3240 RTW_INFO("dbg(0x608)=0x%x\n", rtw_read32(padapter, 0x608));
3241 RTW_INFO("dbg(0x280)=0x%x\n", rtw_read32(padapter, 0x280));
3242 RTW_INFO("dbg(0x284)=0x%x\n", rtw_read32(padapter, 0x284));
3243 RTW_INFO("dbg(0x288)=0x%x\n", rtw_read32(padapter, 0x288));
3244
3245 RTW_INFO("dbg(0x664)=0x%x\n", rtw_read32(padapter, 0x664));
3246
3247
3248 RTW_INFO("\n");
3249
3250 RTW_INFO("dbg(0x430)=0x%x\n", rtw_read32(padapter, 0x430));
3251 RTW_INFO("dbg(0x438)=0x%x\n", rtw_read32(padapter, 0x438));
3252
3253 RTW_INFO("dbg(0x440)=0x%x\n", rtw_read32(padapter, 0x440));
3254
3255 RTW_INFO("dbg(0x458)=0x%x\n", rtw_read32(padapter, 0x458));
3256
3257 RTW_INFO("dbg(0x484)=0x%x\n", rtw_read32(padapter, 0x484));
3258 RTW_INFO("dbg(0x488)=0x%x\n", rtw_read32(padapter, 0x488));
3259
3260 RTW_INFO("dbg(0x444)=0x%x\n", rtw_read32(padapter, 0x444));
3261 RTW_INFO("dbg(0x448)=0x%x\n", rtw_read32(padapter, 0x448));
3262 RTW_INFO("dbg(0x44c)=0x%x\n", rtw_read32(padapter, 0x44c));
3263 RTW_INFO("dbg(0x450)=0x%x\n", rtw_read32(padapter, 0x450));
3264 #endif
3265
3266 return 0;
3267
3268 }
3269 #endif
3270
3271 static int rtw_wx_read32(struct net_device *dev,
3272 struct iw_request_info *info,
3273 union iwreq_data *wrqu, char *extra)
3274 {
3275 PADAPTER padapter;
3276 struct iw_point *p;
3277 u16 len;
3278 u32 addr;
3279 u32 data32;
3280 u32 bytes;
3281 u8 *ptmp;
3282 int ret;
3283
3284
3285 ret = 0;
3286 padapter = (PADAPTER)rtw_netdev_priv(dev);
3287 p = &wrqu->data;
3288 len = p->length;
3289 if (0 == len)
3290 return -EINVAL;
3291
3292 ptmp = (u8 *)rtw_malloc(len);
3293 if (NULL == ptmp)
3294 return -ENOMEM;
3295
3296 if (copy_from_user(ptmp, p->pointer, len)) {
3297 ret = -EFAULT;
3298 goto exit;
3299 }
3300
3301 bytes = 0;
3302 addr = 0;
3303 sscanf(ptmp, "%d,%x", &bytes, &addr);
3304
3305 switch (bytes) {
3306 case 1:
3307 data32 = rtw_read8(padapter, addr);
3308 sprintf(extra, "0x%02X", data32);
3309 break;
3310 case 2:
3311 data32 = rtw_read16(padapter, addr);
3312 sprintf(extra, "0x%04X", data32);
3313 break;
3314 case 4:
3315 data32 = rtw_read32(padapter, addr);
3316 sprintf(extra, "0x%08X", data32);
3317 break;
3318
3319 #if defined(CONFIG_SDIO_HCI) && defined(CONFIG_SDIO_INDIRECT_ACCESS) && defined(DBG_SDIO_INDIRECT_ACCESS)
3320 case 11:
3321 data32 = rtw_sd_iread8(padapter, addr);
3322 sprintf(extra, "0x%02X", data32);
3323 break;
3324 case 12:
3325 data32 = rtw_sd_iread16(padapter, addr);
3326 sprintf(extra, "0x%04X", data32);
3327 break;
3328 case 14:
3329 data32 = rtw_sd_iread32(padapter, addr);
3330 sprintf(extra, "0x%08X", data32);
3331 break;
3332 #endif
3333 default:
3334 RTW_INFO("%s: usage> read [bytes],[address(hex)]\n", __func__);
3335 ret = -EINVAL;
3336 goto exit;
3337 }
3338 RTW_INFO("%s: addr=0x%08X data=%s\n", __func__, addr, extra);
3339
3340 exit:
3341 rtw_mfree(ptmp, len);
3342
3343 return 0;
3344 }
3345
3346 static int rtw_wx_write32(struct net_device *dev,
3347 struct iw_request_info *info,
3348 union iwreq_data *wrqu, char *extra)
3349 {
3350 PADAPTER padapter = (PADAPTER)rtw_netdev_priv(dev);
3351
3352 u32 addr;
3353 u32 data32;
3354 u32 bytes;
3355
3356
3357 bytes = 0;
3358 addr = 0;
3359 data32 = 0;
3360 sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32);
3361
3362 switch (bytes) {
3363 case 1:
3364 rtw_write8(padapter, addr, (u8)data32);
3365 RTW_INFO("%s: addr=0x%08X data=0x%02X\n", __func__, addr, (u8)data32);
3366 break;
3367 case 2:
3368 rtw_write16(padapter, addr, (u16)data32);
3369 RTW_INFO("%s: addr=0x%08X data=0x%04X\n", __func__, addr, (u16)data32);
3370 break;
3371 case 4:
3372 rtw_write32(padapter, addr, data32);
3373 RTW_INFO("%s: addr=0x%08X data=0x%08X\n", __func__, addr, data32);
3374 break;
3375 default:
3376 RTW_INFO("%s: usage> write [bytes],[address(hex)],[data(hex)]\n", __func__);
3377 return -EINVAL;
3378 }
3379
3380 return 0;
3381 }
3382
3383 static int rtw_wx_read_rf(struct net_device *dev,
3384 struct iw_request_info *info,
3385 union iwreq_data *wrqu, char *extra)
3386 {
3387 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3388 u32 path, addr, data32;
3389
3390
3391 path = *(u32 *)extra;
3392 addr = *((u32 *)extra + 1);
3393 data32 = rtw_hal_read_rfreg(padapter, path, addr, 0xFFFFF);
3394 /* RTW_INFO("%s: path=%d addr=0x%02x data=0x%05x\n", __func__, path, addr, data32); */
3395 /*
3396 * IMPORTANT!!
3397 * Only when wireless private ioctl is at odd order,
3398 * "extra" would be copied to user space.
3399 */
3400 sprintf(extra, "0x%05x", data32);
3401
3402 return 0;
3403 }
3404
3405 static int rtw_wx_write_rf(struct net_device *dev,
3406 struct iw_request_info *info,
3407 union iwreq_data *wrqu, char *extra)
3408 {
3409 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3410 u32 path, addr, data32;
3411
3412
3413 path = *(u32 *)extra;
3414 addr = *((u32 *)extra + 1);
3415 data32 = *((u32 *)extra + 2);
3416 /* RTW_INFO("%s: path=%d addr=0x%02x data=0x%05x\n", __func__, path, addr, data32); */
3417 rtw_hal_write_rfreg(padapter, path, addr, 0xFFFFF, data32);
3418
3419 return 0;
3420 }
3421
3422 static int rtw_wx_priv_null(struct net_device *dev, struct iw_request_info *a,
3423 union iwreq_data *wrqu, char *b)
3424 {
3425 return -1;
3426 }
3427
3428 #ifdef CONFIG_RTW_80211K
3429 extern void rm_dbg_cmd(_adapter *padapter, char *s);
3430 static int rtw_wx_priv_rrm(struct net_device *dev, struct iw_request_info *a,
3431 union iwreq_data *wrqu, char *b)
3432 {
3433 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3434 u32 path, addr, data32;
3435
3436
3437 rm_dbg_cmd(padapter, b);
3438 wrqu->data.length = strlen(b);
3439
3440 return 0;
3441 }
3442 #endif
3443
3444 #ifdef CONFIG_IOCTL_WEXT
3445 static int dummy(struct net_device *dev, struct iw_request_info *a,
3446 union iwreq_data *wrqu, char *b)
3447 {
3448 /* _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); */
3449 /* struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); */
3450
3451 /* RTW_INFO("cmd_code=%x, fwstate=0x%x\n", a->cmd, get_fwstate(pmlmepriv)); */
3452
3453 return -1;
3454
3455 }
3456 #endif
3457
3458 static int rtw_wx_set_channel_plan(struct net_device *dev,
3459 struct iw_request_info *info,
3460 union iwreq_data *wrqu, char *extra)
3461 {
3462 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3463 u8 channel_plan_req = (u8)(*((int *)wrqu));
3464
3465 if (_SUCCESS != rtw_set_channel_plan(padapter, channel_plan_req))
3466 return -EPERM;
3467
3468 return 0;
3469 }
3470
3471 static int rtw_wx_set_mtk_wps_probe_ie(struct net_device *dev,
3472 struct iw_request_info *a,
3473 union iwreq_data *wrqu, char *b)
3474 {
3475 #ifdef CONFIG_PLATFORM_MT53XX
3476 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3477 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3478
3479 #endif
3480 return 0;
3481 }
3482
3483 static int rtw_wx_get_sensitivity(struct net_device *dev,
3484 struct iw_request_info *info,
3485 union iwreq_data *wrqu, char *buf)
3486 {
3487 #ifdef CONFIG_PLATFORM_MT53XX
3488 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3489
3490 /* Modified by Albert 20110914 */
3491 /* This is in dbm format for MTK platform. */
3492 wrqu->qual.level = padapter->recvpriv.rssi;
3493 RTW_INFO(" level = %u\n", wrqu->qual.level);
3494 #endif
3495 return 0;
3496 }
3497
3498 static int rtw_wx_set_mtk_wps_ie(struct net_device *dev,
3499 struct iw_request_info *info,
3500 union iwreq_data *wrqu, char *extra)
3501 {
3502 #ifdef CONFIG_PLATFORM_MT53XX
3503 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3504
3505 return rtw_set_wpa_ie(padapter, wrqu->data.pointer, wrqu->data.length);
3506 #else
3507 return 0;
3508 #endif
3509 }
3510
3511 #ifdef MP_IOCTL_HDL
3512 static void rtw_dbg_mode_hdl(_adapter *padapter, u32 id, u8 *pdata, u32 len)
3513 {
3514 pRW_Reg RegRWStruct;
3515 struct rf_reg_param *prfreg;
3516 u8 path;
3517 u8 offset;
3518 u32 value;
3519
3520 RTW_INFO("%s\n", __FUNCTION__);
3521
3522 switch (id) {
3523 case GEN_MP_IOCTL_SUBCODE(MP_START):
3524 RTW_INFO("871x_driver is only for normal mode, can't enter mp mode\n");
3525 break;
3526 case GEN_MP_IOCTL_SUBCODE(READ_REG):
3527 RegRWStruct = (pRW_Reg)pdata;
3528 switch (RegRWStruct->width) {
3529 case 1:
3530 RegRWStruct->value = rtw_read8(padapter, RegRWStruct->offset);
3531 break;
3532 case 2:
3533 RegRWStruct->value = rtw_read16(padapter, RegRWStruct->offset);
3534 break;
3535 case 4:
3536 RegRWStruct->value = rtw_read32(padapter, RegRWStruct->offset);
3537 break;
3538 default:
3539 break;
3540 }
3541
3542 break;
3543 case GEN_MP_IOCTL_SUBCODE(WRITE_REG):
3544 RegRWStruct = (pRW_Reg)pdata;
3545 switch (RegRWStruct->width) {
3546 case 1:
3547 rtw_write8(padapter, RegRWStruct->offset, (u8)RegRWStruct->value);
3548 break;
3549 case 2:
3550 rtw_write16(padapter, RegRWStruct->offset, (u16)RegRWStruct->value);
3551 break;
3552 case 4:
3553 rtw_write32(padapter, RegRWStruct->offset, (u32)RegRWStruct->value);
3554 break;
3555 default:
3556 break;
3557 }
3558
3559 break;
3560 case GEN_MP_IOCTL_SUBCODE(READ_RF_REG):
3561
3562 prfreg = (struct rf_reg_param *)pdata;
3563
3564 path = (u8)prfreg->path;
3565 offset = (u8)prfreg->offset;
3566
3567 value = rtw_hal_read_rfreg(padapter, path, offset, 0xffffffff);
3568
3569 prfreg->value = value;
3570
3571 break;
3572 case GEN_MP_IOCTL_SUBCODE(WRITE_RF_REG):
3573
3574 prfreg = (struct rf_reg_param *)pdata;
3575
3576 path = (u8)prfreg->path;
3577 offset = (u8)prfreg->offset;
3578 value = prfreg->value;
3579
3580 rtw_hal_write_rfreg(padapter, path, offset, 0xffffffff, value);
3581
3582 break;
3583 case GEN_MP_IOCTL_SUBCODE(TRIGGER_GPIO):
3584 RTW_INFO("==> trigger gpio 0\n");
3585 rtw_hal_set_hwreg(padapter, HW_VAR_TRIGGER_GPIO_0, 0);
3586 break;
3587 #ifdef CONFIG_BT_COEXIST
3588 case GEN_MP_IOCTL_SUBCODE(SET_DM_BT):
3589 RTW_INFO("==> set dm_bt_coexist:%x\n", *(u8 *)pdata);
3590 rtw_hal_set_hwreg(padapter, HW_VAR_BT_SET_COEXIST, pdata);
3591 break;
3592 case GEN_MP_IOCTL_SUBCODE(DEL_BA):
3593 RTW_INFO("==> delete ba:%x\n", *(u8 *)pdata);
3594 rtw_hal_set_hwreg(padapter, HW_VAR_BT_ISSUE_DELBA, pdata);
3595 break;
3596 #endif
3597 #ifdef DBG_CONFIG_ERROR_DETECT
3598 case GEN_MP_IOCTL_SUBCODE(GET_WIFI_STATUS):
3599 *pdata = rtw_hal_sreset_get_wifi_status(padapter);
3600 break;
3601 #endif
3602
3603 default:
3604 break;
3605 }
3606
3607 }
3608 static int rtw_mp_ioctl_hdl(struct net_device *dev, struct iw_request_info *info,
3609 union iwreq_data *wrqu, char *extra)
3610 {
3611 int ret = 0;
3612 u32 BytesRead, BytesWritten, BytesNeeded;
3613 struct oid_par_priv oid_par;
3614 struct mp_ioctl_handler *phandler;
3615 struct mp_ioctl_param *poidparam;
3616 uint status = 0;
3617 u16 len;
3618 u8 *pparmbuf = NULL, bset;
3619 PADAPTER padapter = (PADAPTER)rtw_netdev_priv(dev);
3620 struct iw_point *p = &wrqu->data;
3621
3622 /* RTW_INFO("+rtw_mp_ioctl_hdl\n"); */
3623
3624 /* mutex_lock(&ioctl_mutex); */
3625
3626 if ((!p->length) || (!p->pointer)) {
3627 ret = -EINVAL;
3628 goto _rtw_mp_ioctl_hdl_exit;
3629 }
3630
3631 pparmbuf = NULL;
3632 bset = (u8)(p->flags & 0xFFFF);
3633 len = p->length;
3634 pparmbuf = (u8 *)rtw_malloc(len);
3635 if (pparmbuf == NULL) {
3636 ret = -ENOMEM;
3637 goto _rtw_mp_ioctl_hdl_exit;
3638 }
3639
3640 if (copy_from_user(pparmbuf, p->pointer, len)) {
3641 ret = -EFAULT;
3642 goto _rtw_mp_ioctl_hdl_exit;
3643 }
3644
3645 poidparam = (struct mp_ioctl_param *)pparmbuf;
3646
3647 if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
3648 ret = -EINVAL;
3649 goto _rtw_mp_ioctl_hdl_exit;
3650 }
3651
3652 /* RTW_INFO("%s: %d\n", __func__, poidparam->subcode); */
3653 #ifdef CONFIG_MP_INCLUDED
3654 if (padapter->registrypriv.mp_mode == 1) {
3655 phandler = mp_ioctl_hdl + poidparam->subcode;
3656
3657 if ((phandler->paramsize != 0) && (poidparam->len < phandler->paramsize)) {
3658 ret = -EINVAL;
3659 goto _rtw_mp_ioctl_hdl_exit;
3660 }
3661
3662 if (phandler->handler) {
3663 oid_par.adapter_context = padapter;
3664 oid_par.oid = phandler->oid;
3665 oid_par.information_buf = poidparam->data;
3666 oid_par.information_buf_len = poidparam->len;
3667 oid_par.dbg = 0;
3668
3669 BytesWritten = 0;
3670 BytesNeeded = 0;
3671
3672 if (bset) {
3673 oid_par.bytes_rw = &BytesRead;
3674 oid_par.bytes_needed = &BytesNeeded;
3675 oid_par.type_of_oid = SET_OID;
3676 } else {
3677 oid_par.bytes_rw = &BytesWritten;
3678 oid_par.bytes_needed = &BytesNeeded;
3679 oid_par.type_of_oid = QUERY_OID;
3680 }
3681
3682 status = phandler->handler(&oid_par);
3683
3684 /* todo:check status, BytesNeeded, etc. */
3685 } else {
3686 RTW_INFO("rtw_mp_ioctl_hdl(): err!, subcode=%d, oid=%d, handler=%p\n",
3687 poidparam->subcode, phandler->oid, phandler->handler);
3688 ret = -EFAULT;
3689 goto _rtw_mp_ioctl_hdl_exit;
3690 }
3691 } else
3692 #endif
3693 {
3694 rtw_dbg_mode_hdl(padapter, poidparam->subcode, poidparam->data, poidparam->len);
3695 }
3696
3697 if (bset == 0x00) {/* query info */
3698 if (copy_to_user(p->pointer, pparmbuf, len))
3699 ret = -EFAULT;
3700 }
3701
3702 if (status) {
3703 ret = -EFAULT;
3704 goto _rtw_mp_ioctl_hdl_exit;
3705 }
3706
3707 _rtw_mp_ioctl_hdl_exit:
3708
3709 if (pparmbuf)
3710 rtw_mfree(pparmbuf, len);
3711
3712 /* mutex_unlock(&ioctl_mutex); */
3713
3714 return ret;
3715 }
3716 #endif /*MP_IOCTL_HDL*/
3717 static int rtw_get_ap_info(struct net_device *dev,
3718 struct iw_request_info *info,
3719 union iwreq_data *wrqu, char *extra)
3720 {
3721 int ret = 0;
3722 u32 cnt = 0, wpa_ielen;
3723 _irqL irqL;
3724 _list *plist, *phead;
3725 unsigned char *pbuf;
3726 u8 bssid[ETH_ALEN];
3727 char data[32];
3728 struct wlan_network *pnetwork = NULL;
3729 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3730 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3731 _queue *queue = &(pmlmepriv->scanned_queue);
3732 struct iw_point *pdata = &wrqu->data;
3733
3734 RTW_INFO("+rtw_get_aplist_info\n");
3735
3736 if (rtw_is_drv_stopped(padapter) || (pdata == NULL)) {
3737 ret = -EINVAL;
3738 goto exit;
3739 }
3740
3741 while ((check_fwstate(pmlmepriv, (WIFI_UNDER_SURVEY | WIFI_UNDER_LINKING))) == _TRUE) {
3742 rtw_msleep_os(30);
3743 cnt++;
3744 if (cnt > 100)
3745 break;
3746 }
3747
3748
3749 /* pdata->length = 0; */ /* ? */
3750 pdata->flags = 0;
3751 if (pdata->length >= 32) {
3752 if (copy_from_user(data, pdata->pointer, 32)) {
3753 ret = -EINVAL;
3754 goto exit;
3755 }
3756 } else {
3757 ret = -EINVAL;
3758 goto exit;
3759 }
3760
3761 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
3762
3763 phead = get_list_head(queue);
3764 plist = get_next(phead);
3765
3766 while (1) {
3767 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
3768 break;
3769
3770
3771 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
3772
3773 /* if(hwaddr_aton_i(pdata->pointer, bssid)) */
3774 if (hwaddr_aton_i(data, bssid)) {
3775 RTW_INFO("Invalid BSSID '%s'.\n", (u8 *)data);
3776 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
3777 return -EINVAL;
3778 }
3779
3780
3781 if (_rtw_memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN) == _TRUE) { /* BSSID match, then check if supporting wpa/wpa2 */
3782 RTW_INFO("BSSID:" MAC_FMT "\n", MAC_ARG(bssid));
3783
3784 pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength - 12);
3785 if (pbuf && (wpa_ielen > 0)) {
3786 pdata->flags = 1;
3787 break;
3788 }
3789
3790 pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength - 12);
3791 if (pbuf && (wpa_ielen > 0)) {
3792 pdata->flags = 2;
3793 break;
3794 }
3795
3796 }
3797
3798 plist = get_next(plist);
3799
3800 }
3801
3802 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
3803
3804 if (pdata->length >= 34) {
3805 if (copy_to_user((u8 *)pdata->pointer + 32, (u8 *)&pdata->flags, 1)) {
3806 ret = -EINVAL;
3807 goto exit;
3808 }
3809 }
3810
3811 exit:
3812
3813 return ret;
3814
3815 }
3816
3817 static int rtw_set_pid(struct net_device *dev,
3818 struct iw_request_info *info,
3819 union iwreq_data *wrqu, char *extra)
3820 {
3821
3822 int ret = 0;
3823 _adapter *padapter = rtw_netdev_priv(dev);
3824 int *pdata = (int *)wrqu;
3825 int selector;
3826
3827 if (rtw_is_drv_stopped(padapter) || (pdata == NULL)) {
3828 ret = -EINVAL;
3829 goto exit;
3830 }
3831
3832 selector = *pdata;
3833 if (selector < 3 && selector >= 0) {
3834 padapter->pid[selector] = *(pdata + 1);
3835 #ifdef CONFIG_GLOBAL_UI_PID
3836 ui_pid[selector] = *(pdata + 1);
3837 #endif
3838 RTW_INFO("%s set pid[%d]=%d\n", __FUNCTION__, selector , padapter->pid[selector]);
3839 } else
3840 RTW_INFO("%s selector %d error\n", __FUNCTION__, selector);
3841
3842 exit:
3843
3844 return ret;
3845
3846 }
3847
3848 static int rtw_wps_start(struct net_device *dev,
3849 struct iw_request_info *info,
3850 union iwreq_data *wrqu, char *extra)
3851 {
3852
3853 int ret = 0;
3854 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3855 struct iw_point *pdata = &wrqu->data;
3856 u32 u32wps_start = 0;
3857 unsigned int uintRet = 0;
3858
3859 if (RTW_CANNOT_RUN(padapter) || (NULL == pdata)) {
3860 ret = -EINVAL;
3861 goto exit;
3862 }
3863
3864 uintRet = copy_from_user((void *) &u32wps_start, pdata->pointer, 4);
3865 if (u32wps_start == 0)
3866 u32wps_start = *extra;
3867
3868 RTW_INFO("[%s] wps_start = %d\n", __FUNCTION__, u32wps_start);
3869
3870 if (u32wps_start == 1) /* WPS Start */
3871 rtw_led_control(padapter, LED_CTL_START_WPS);
3872 else if (u32wps_start == 2) /* WPS Stop because of wps success */
3873 rtw_led_control(padapter, LED_CTL_STOP_WPS);
3874 else if (u32wps_start == 3) /* WPS Stop because of wps fail */
3875 rtw_led_control(padapter, LED_CTL_STOP_WPS_FAIL);
3876
3877 exit:
3878
3879 return ret;
3880
3881 }
3882
3883 #ifdef CONFIG_P2P
3884 static int rtw_wext_p2p_enable(struct net_device *dev,
3885 struct iw_request_info *info,
3886 union iwreq_data *wrqu, char *extra)
3887 {
3888
3889 int ret = 0;
3890 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3891 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3892 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3893 enum P2P_ROLE init_role = P2P_ROLE_DISABLE;
3894 #ifdef CONFIG_CONCURRENT_MODE
3895 struct roch_info *prochinfo = &padapter->rochinfo;
3896 #endif
3897
3898 if (*extra == '0')
3899 init_role = P2P_ROLE_DISABLE;
3900 else if (*extra == '1')
3901 init_role = P2P_ROLE_DEVICE;
3902 else if (*extra == '2')
3903 init_role = P2P_ROLE_CLIENT;
3904 else if (*extra == '3')
3905 init_role = P2P_ROLE_GO;
3906
3907 if (_FAIL == rtw_p2p_enable(padapter, init_role)) {
3908 ret = -EFAULT;
3909 goto exit;
3910 }
3911
3912 /* set channel/bandwidth */
3913 if (init_role != P2P_ROLE_DISABLE) {
3914 u8 channel, ch_offset;
3915 u16 bwmode;
3916
3917 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN)) {
3918 /* Stay at the listen state and wait for discovery. */
3919 channel = pwdinfo->listen_channel;
3920 pwdinfo->operating_channel = pwdinfo->listen_channel;
3921 ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
3922 bwmode = CHANNEL_WIDTH_20;
3923 }
3924 #ifdef CONFIG_CONCURRENT_MODE
3925 else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
3926
3927 _set_timer(&prochinfo->ap_roch_ch_switch_timer, pwdinfo->ext_listen_interval);
3928
3929 channel = rtw_mi_get_union_chan(padapter);
3930 ch_offset = rtw_mi_get_union_offset(padapter);
3931 bwmode = rtw_mi_get_union_bw(padapter);
3932
3933 pwdinfo->operating_channel = channel;
3934 }
3935 #endif
3936 else {
3937 pwdinfo->operating_channel = pmlmeext->cur_channel;
3938
3939 channel = pwdinfo->operating_channel;
3940 ch_offset = pmlmeext->cur_ch_offset;
3941 bwmode = pmlmeext->cur_bwmode;
3942 }
3943
3944 set_channel_bwmode(padapter, channel, ch_offset, bwmode);
3945 }
3946
3947 exit:
3948 return ret;
3949
3950 }
3951
3952 static int rtw_p2p_set_go_nego_ssid(struct net_device *dev,
3953 struct iw_request_info *info,
3954 union iwreq_data *wrqu, char *extra)
3955 {
3956
3957 int ret = 0;
3958 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3959 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3960
3961 RTW_INFO("[%s] ssid = %s, len = %zu\n", __FUNCTION__, extra, strlen(extra));
3962 _rtw_memcpy(pwdinfo->nego_ssid, extra, strlen(extra));
3963 pwdinfo->nego_ssidlen = strlen(extra);
3964
3965 return ret;
3966
3967 }
3968
3969
3970 static int rtw_p2p_set_intent(struct net_device *dev,
3971 struct iw_request_info *info,
3972 union iwreq_data *wrqu, char *extra)
3973 {
3974 int ret = 0;
3975 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
3976 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3977 u8 intent = pwdinfo->intent;
3978
3979 extra[wrqu->data.length] = 0x00;
3980
3981 intent = rtw_atoi(extra);
3982
3983 if (intent <= 15)
3984 pwdinfo->intent = intent;
3985 else
3986 ret = -1;
3987
3988 RTW_INFO("[%s] intent = %d\n", __FUNCTION__, intent);
3989
3990 return ret;
3991
3992 }
3993
3994 static int rtw_p2p_set_listen_ch(struct net_device *dev,
3995 struct iw_request_info *info,
3996 union iwreq_data *wrqu, char *extra)
3997 {
3998
3999 int ret = 0;
4000 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4001 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4002 u8 listen_ch = pwdinfo->listen_channel; /* Listen channel number */
4003
4004 extra[wrqu->data.length] = 0x00;
4005 listen_ch = rtw_atoi(extra);
4006
4007 if ((listen_ch == 1) || (listen_ch == 6) || (listen_ch == 11)) {
4008 pwdinfo->listen_channel = listen_ch;
4009 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
4010 } else
4011 ret = -1;
4012
4013 RTW_INFO("[%s] listen_ch = %d\n", __FUNCTION__, pwdinfo->listen_channel);
4014
4015 return ret;
4016
4017 }
4018
4019 static int rtw_p2p_set_op_ch(struct net_device *dev,
4020 struct iw_request_info *info,
4021 union iwreq_data *wrqu, char *extra)
4022 {
4023 /* Commented by Albert 20110524
4024 * This function is used to set the operating channel if the driver will become the group owner */
4025
4026 int ret = 0;
4027 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4028 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4029 u8 op_ch = pwdinfo->operating_channel; /* Operating channel number */
4030
4031 extra[wrqu->data.length] = 0x00;
4032
4033 op_ch = (u8) rtw_atoi(extra);
4034 if (op_ch > 0)
4035 pwdinfo->operating_channel = op_ch;
4036 else
4037 ret = -1;
4038
4039 RTW_INFO("[%s] op_ch = %d\n", __FUNCTION__, pwdinfo->operating_channel);
4040
4041 return ret;
4042
4043 }
4044
4045
4046 static int rtw_p2p_profilefound(struct net_device *dev,
4047 struct iw_request_info *info,
4048 union iwreq_data *wrqu, char *extra)
4049 {
4050
4051 int ret = 0;
4052 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4053 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4054
4055 /* Comment by Albert 2010/10/13 */
4056 /* Input data format: */
4057 /* Ex: 0 */
4058 /* Ex: 1XX:XX:XX:XX:XX:XXYYSSID */
4059 /* 0 => Reflush the profile record list. */
4060 /* 1 => Add the profile list */
4061 /* XX:XX:XX:XX:XX:XX => peer's MAC Address ( ex: 00:E0:4C:00:00:01 ) */
4062 /* YY => SSID Length */
4063 /* SSID => SSID for persistence group */
4064
4065 RTW_INFO("[%s] In value = %s, len = %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
4066
4067
4068 /* The upper application should pass the SSID to driver by using this rtw_p2p_profilefound function. */
4069 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
4070 if (extra[0] == '0') {
4071 /* Remove all the profile information of wifidirect_info structure. */
4072 _rtw_memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
4073 pwdinfo->profileindex = 0;
4074 } else {
4075 if (pwdinfo->profileindex >= P2P_MAX_PERSISTENT_GROUP_NUM)
4076 ret = -1;
4077 else {
4078 int jj, kk;
4079
4080 /* Add this profile information into pwdinfo->profileinfo */
4081 /* Ex: 1XX:XX:XX:XX:XX:XXYYSSID */
4082 for (jj = 0, kk = 1; jj < ETH_ALEN; jj++, kk += 3)
4083 pwdinfo->profileinfo[pwdinfo->profileindex].peermac[jj] = key_2char2num(extra[kk], extra[kk + 1]);
4084
4085 /* pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen = ( extra[18] - '0' ) * 10 + ( extra[19] - '0' ); */
4086 /* _rtw_memcpy( pwdinfo->profileinfo[pwdinfo->profileindex].ssid, &extra[20], pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen ); */
4087 pwdinfo->profileindex++;
4088 }
4089 }
4090 }
4091
4092 return ret;
4093
4094 }
4095
4096 static int rtw_p2p_setDN(struct net_device *dev,
4097 struct iw_request_info *info,
4098 union iwreq_data *wrqu, char *extra)
4099 {
4100
4101 int ret = 0;
4102 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4103 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4104
4105
4106 RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
4107 _rtw_memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
4108 _rtw_memcpy(pwdinfo->device_name, extra, wrqu->data.length - 1);
4109 pwdinfo->device_name_len = wrqu->data.length - 1;
4110
4111 return ret;
4112
4113 }
4114
4115
4116 static int rtw_p2p_get_status(struct net_device *dev,
4117 struct iw_request_info *info,
4118 union iwreq_data *wrqu, char *extra)
4119 {
4120
4121 int ret = 0;
4122 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4123 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4124
4125 if (padapter->bShowGetP2PState) {
4126 RTW_INFO("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
4127 pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
4128 pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
4129 }
4130
4131 /* Commented by Albert 2010/10/12 */
4132 /* Because of the output size limitation, I had removed the "Role" information. */
4133 /* About the "Role" information, we will use the new private IOCTL to get the "Role" information. */
4134 sprintf(extra, "\n\nStatus=%.2d\n", rtw_p2p_state(pwdinfo));
4135 wrqu->data.length = strlen(extra);
4136
4137 return ret;
4138
4139 }
4140
4141 /* Commented by Albert 20110520
4142 * This function will return the config method description
4143 * This config method description will show us which config method the remote P2P device is intented to use
4144 * by sending the provisioning discovery request frame. */
4145
4146 static int rtw_p2p_get_req_cm(struct net_device *dev,
4147 struct iw_request_info *info,
4148 union iwreq_data *wrqu, char *extra)
4149 {
4150
4151 int ret = 0;
4152 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4153 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4154
4155 sprintf(extra, "\n\nCM=%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
4156 wrqu->data.length = strlen(extra);
4157 return ret;
4158
4159 }
4160
4161
4162 static int rtw_p2p_get_role(struct net_device *dev,
4163 struct iw_request_info *info,
4164 union iwreq_data *wrqu, char *extra)
4165 {
4166
4167 int ret = 0;
4168 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4169 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4170
4171 RTW_INFO("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
4172 pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
4173 pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
4174
4175 sprintf(extra, "\n\nRole=%.2d\n", rtw_p2p_role(pwdinfo));
4176 wrqu->data.length = strlen(extra);
4177 return ret;
4178
4179 }
4180
4181
4182 static int rtw_p2p_get_peer_ifaddr(struct net_device *dev,
4183 struct iw_request_info *info,
4184 union iwreq_data *wrqu, char *extra)
4185 {
4186
4187 int ret = 0;
4188 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4189 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4190
4191
4192 RTW_INFO("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
4193 pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
4194 pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
4195
4196 sprintf(extra, "\nMAC %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
4197 pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
4198 pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
4199 wrqu->data.length = strlen(extra);
4200 return ret;
4201
4202 }
4203
4204 static int rtw_p2p_get_peer_devaddr(struct net_device *dev,
4205 struct iw_request_info *info,
4206 union iwreq_data *wrqu, char *extra)
4207
4208 {
4209
4210 int ret = 0;
4211 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4212 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4213
4214 RTW_INFO("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
4215 pwdinfo->rx_prov_disc_info.peerDevAddr[0], pwdinfo->rx_prov_disc_info.peerDevAddr[1],
4216 pwdinfo->rx_prov_disc_info.peerDevAddr[2], pwdinfo->rx_prov_disc_info.peerDevAddr[3],
4217 pwdinfo->rx_prov_disc_info.peerDevAddr[4], pwdinfo->rx_prov_disc_info.peerDevAddr[5]);
4218 sprintf(extra, "\n%.2X%.2X%.2X%.2X%.2X%.2X",
4219 pwdinfo->rx_prov_disc_info.peerDevAddr[0], pwdinfo->rx_prov_disc_info.peerDevAddr[1],
4220 pwdinfo->rx_prov_disc_info.peerDevAddr[2], pwdinfo->rx_prov_disc_info.peerDevAddr[3],
4221 pwdinfo->rx_prov_disc_info.peerDevAddr[4], pwdinfo->rx_prov_disc_info.peerDevAddr[5]);
4222 wrqu->data.length = strlen(extra);
4223 return ret;
4224
4225 }
4226
4227 static int rtw_p2p_get_peer_devaddr_by_invitation(struct net_device *dev,
4228 struct iw_request_info *info,
4229 union iwreq_data *wrqu, char *extra)
4230
4231 {
4232
4233 int ret = 0;
4234 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4235 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4236
4237 RTW_INFO("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __FUNCTION__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
4238 pwdinfo->p2p_peer_device_addr[0], pwdinfo->p2p_peer_device_addr[1],
4239 pwdinfo->p2p_peer_device_addr[2], pwdinfo->p2p_peer_device_addr[3],
4240 pwdinfo->p2p_peer_device_addr[4], pwdinfo->p2p_peer_device_addr[5]);
4241 sprintf(extra, "\nMAC %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
4242 pwdinfo->p2p_peer_device_addr[0], pwdinfo->p2p_peer_device_addr[1],
4243 pwdinfo->p2p_peer_device_addr[2], pwdinfo->p2p_peer_device_addr[3],
4244 pwdinfo->p2p_peer_device_addr[4], pwdinfo->p2p_peer_device_addr[5]);
4245 wrqu->data.length = strlen(extra);
4246 return ret;
4247
4248 }
4249
4250 static int rtw_p2p_get_groupid(struct net_device *dev,
4251 struct iw_request_info *info,
4252 union iwreq_data *wrqu, char *extra)
4253
4254 {
4255
4256 int ret = 0;
4257 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4258 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4259
4260 sprintf(extra, "\n%.2X:%.2X:%.2X:%.2X:%.2X:%.2X %s",
4261 pwdinfo->groupid_info.go_device_addr[0], pwdinfo->groupid_info.go_device_addr[1],
4262 pwdinfo->groupid_info.go_device_addr[2], pwdinfo->groupid_info.go_device_addr[3],
4263 pwdinfo->groupid_info.go_device_addr[4], pwdinfo->groupid_info.go_device_addr[5],
4264 pwdinfo->groupid_info.ssid);
4265 wrqu->data.length = strlen(extra);
4266 return ret;
4267
4268 }
4269
4270 static int rtw_p2p_get_op_ch(struct net_device *dev,
4271 struct iw_request_info *info,
4272 union iwreq_data *wrqu, char *extra)
4273
4274 {
4275
4276 int ret = 0;
4277 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4278 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4279
4280
4281 RTW_INFO("[%s] Op_ch = %02x\n", __FUNCTION__, pwdinfo->operating_channel);
4282
4283 sprintf(extra, "\n\nOp_ch=%.2d\n", pwdinfo->operating_channel);
4284 wrqu->data.length = strlen(extra);
4285 return ret;
4286
4287 }
4288
4289 static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
4290 struct iw_request_info *info,
4291 union iwreq_data *wrqu, char *extra, char *subcmd)
4292 {
4293
4294 int ret = 0;
4295 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4296 u8 peerMAC[ETH_ALEN] = { 0x00 };
4297 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4298 _irqL irqL;
4299 _list *plist, *phead;
4300 _queue *queue = &(pmlmepriv->scanned_queue);
4301 struct wlan_network *pnetwork = NULL;
4302 u8 blnMatch = 0;
4303 u16 attr_content = 0;
4304 uint attr_contentlen = 0;
4305 u8 attr_content_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
4306
4307 /* Commented by Albert 20110727 */
4308 /* The input data is the MAC address which the application wants to know its WPS config method. */
4309 /* After knowing its WPS config method, the application can decide the config method for provisioning discovery. */
4310 /* Format: iwpriv wlanx p2p_get_wpsCM 00:E0:4C:00:00:05 */
4311
4312 RTW_INFO("[%s] data = %s\n", __FUNCTION__, subcmd);
4313
4314 macstr2num(peerMAC, subcmd);
4315
4316 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4317
4318 phead = get_list_head(queue);
4319 plist = get_next(phead);
4320
4321 while (1) {
4322 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
4323 break;
4324
4325 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
4326 if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
4327 u8 *wpsie;
4328 uint wpsie_len = 0;
4329
4330 /* The mac address is matched. */
4331
4332 wpsie = rtw_get_wps_ie_from_scan_queue(&pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &wpsie_len, pnetwork->network.Reserved[0]);
4333 if (wpsie) {
4334 attr_contentlen = sizeof(attr_content);
4335 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *)&attr_content, &attr_contentlen);
4336 if (attr_contentlen) {
4337 attr_content = be16_to_cpu(attr_content);
4338 sprintf(attr_content_str, "\n\nM=%.4d", attr_content);
4339 blnMatch = 1;
4340 }
4341 }
4342
4343 break;
4344 }
4345
4346 plist = get_next(plist);
4347
4348 }
4349
4350 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4351
4352 if (!blnMatch)
4353 sprintf(attr_content_str, "\n\nM=0000");
4354
4355 wrqu->data.length = strlen(attr_content_str);
4356 _rtw_memcpy(extra, attr_content_str, wrqu->data.length);
4357
4358 return ret;
4359
4360 }
4361
4362 #ifdef CONFIG_WFD
4363 static int rtw_p2p_get_peer_wfd_port(struct net_device *dev,
4364 struct iw_request_info *info,
4365 union iwreq_data *wrqu, char *extra)
4366 {
4367
4368 int ret = 0;
4369 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4370 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4371
4372 RTW_INFO("[%s] p2p_state = %d\n", __FUNCTION__, rtw_p2p_state(pwdinfo));
4373
4374 sprintf(extra, "\n\nPort=%d\n", pwdinfo->wfd_info->peer_rtsp_ctrlport);
4375 RTW_INFO("[%s] remote port = %d\n", __FUNCTION__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
4376
4377 wrqu->data.length = strlen(extra);
4378 return ret;
4379
4380 }
4381
4382 static int rtw_p2p_get_peer_wfd_preferred_connection(struct net_device *dev,
4383 struct iw_request_info *info,
4384 union iwreq_data *wrqu, char *extra)
4385 {
4386
4387 int ret = 0;
4388 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4389 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4390
4391 sprintf(extra, "\n\nwfd_pc=%d\n", pwdinfo->wfd_info->wfd_pc);
4392 RTW_INFO("[%s] wfd_pc = %d\n", __FUNCTION__, pwdinfo->wfd_info->wfd_pc);
4393
4394 wrqu->data.length = strlen(extra);
4395 pwdinfo->wfd_info->wfd_pc = _FALSE; /* Reset the WFD preferred connection to P2P */
4396 return ret;
4397
4398 }
4399
4400 static int rtw_p2p_get_peer_wfd_session_available(struct net_device *dev,
4401 struct iw_request_info *info,
4402 union iwreq_data *wrqu, char *extra)
4403 {
4404
4405 int ret = 0;
4406 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4407 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4408
4409 sprintf(extra, "\n\nwfd_sa=%d\n", pwdinfo->wfd_info->peer_session_avail);
4410 RTW_INFO("[%s] wfd_sa = %d\n", __FUNCTION__, pwdinfo->wfd_info->peer_session_avail);
4411
4412 wrqu->data.length = strlen(extra);
4413 pwdinfo->wfd_info->peer_session_avail = _TRUE; /* Reset the WFD session available */
4414 return ret;
4415
4416 }
4417 #endif /* CONFIG_WFD */
4418
4419 static int rtw_p2p_get_go_device_address(struct net_device *dev,
4420 struct iw_request_info *info,
4421 union iwreq_data *wrqu, char *extra, char *subcmd)
4422 {
4423
4424 int ret = 0;
4425 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4426 u8 peerMAC[ETH_ALEN] = { 0x00 };
4427 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4428 _irqL irqL;
4429 _list *plist, *phead;
4430 _queue *queue = &(pmlmepriv->scanned_queue);
4431 struct wlan_network *pnetwork = NULL;
4432 u8 blnMatch = 0;
4433 u8 *p2pie;
4434 uint p2pielen = 0, attr_contentlen = 0;
4435 u8 attr_content[100] = { 0x00 };
4436 u8 go_devadd_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
4437
4438 /* Commented by Albert 20121209 */
4439 /* The input data is the GO's interface address which the application wants to know its device address. */
4440 /* Format: iwpriv wlanx p2p_get2 go_devadd=00:E0:4C:00:00:05 */
4441
4442 RTW_INFO("[%s] data = %s\n", __FUNCTION__, subcmd);
4443
4444 macstr2num(peerMAC, subcmd);
4445
4446 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4447
4448 phead = get_list_head(queue);
4449 plist = get_next(phead);
4450
4451 while (1) {
4452 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
4453 break;
4454
4455 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
4456 if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
4457 /* Commented by Albert 2011/05/18 */
4458 /* Match the device address located in the P2P IE */
4459 /* This is for the case that the P2P device address is not the same as the P2P interface address. */
4460
4461 p2pie = rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen);
4462 if (p2pie) {
4463 while (p2pie) {
4464 /* The P2P Device ID attribute is included in the Beacon frame. */
4465 /* The P2P Device Info attribute is included in the probe response frame. */
4466
4467 _rtw_memset(attr_content, 0x00, 100);
4468 attr_contentlen = sizeof(attr_content);
4469 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
4470 /* Handle the P2P Device ID attribute of Beacon first */
4471 blnMatch = 1;
4472 break;
4473
4474 } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
4475 /* Handle the P2P Device Info attribute of probe response */
4476 blnMatch = 1;
4477 break;
4478 }
4479
4480 /* Get the next P2P IE */
4481 p2pie = rtw_get_p2p_ie(p2pie + p2pielen, BSS_EX_TLV_IES_LEN(&pnetwork->network) - (p2pie + p2pielen - BSS_EX_TLV_IES(&pnetwork->network)), NULL, &p2pielen);
4482 }
4483 }
4484 }
4485
4486 plist = get_next(plist);
4487
4488 }
4489
4490 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4491
4492 if (!blnMatch)
4493 sprintf(go_devadd_str, "\n\ndev_add=NULL");
4494 else {
4495 sprintf(go_devadd_str, "\n\ndev_add=%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
4496 attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]);
4497 }
4498
4499 wrqu->data.length = strlen(go_devadd_str);
4500 _rtw_memcpy(extra, go_devadd_str, wrqu->data.length);
4501
4502 return ret;
4503
4504 }
4505
4506 static int rtw_p2p_get_device_type(struct net_device *dev,
4507 struct iw_request_info *info,
4508 union iwreq_data *wrqu, char *extra, char *subcmd)
4509 {
4510
4511 int ret = 0;
4512 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4513 u8 peerMAC[ETH_ALEN] = { 0x00 };
4514 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4515 _irqL irqL;
4516 _list *plist, *phead;
4517 _queue *queue = &(pmlmepriv->scanned_queue);
4518 struct wlan_network *pnetwork = NULL;
4519 u8 blnMatch = 0;
4520 u8 dev_type[8] = { 0x00 };
4521 uint dev_type_len = 0;
4522 u8 dev_type_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 }; /* +9 is for the str "dev_type=", we have to clear it at wrqu->data.pointer */
4523
4524 /* Commented by Albert 20121209 */
4525 /* The input data is the MAC address which the application wants to know its device type. */
4526 /* Such user interface could know the device type. */
4527 /* Format: iwpriv wlanx p2p_get2 dev_type=00:E0:4C:00:00:05 */
4528
4529 RTW_INFO("[%s] data = %s\n", __FUNCTION__, subcmd);
4530
4531 macstr2num(peerMAC, subcmd);
4532
4533 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4534
4535 phead = get_list_head(queue);
4536 plist = get_next(phead);
4537
4538 while (1) {
4539 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
4540 break;
4541
4542 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
4543 if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
4544 u8 *wpsie;
4545 uint wpsie_len = 0;
4546
4547 /* The mac address is matched. */
4548
4549 wpsie = rtw_get_wps_ie_from_scan_queue(&pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &wpsie_len, pnetwork->network.Reserved[0]);
4550 if (wpsie) {
4551 dev_type_len = sizeof(dev_type);
4552 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_PRIMARY_DEV_TYPE, dev_type, &dev_type_len);
4553 if (dev_type_len) {
4554 u16 type = 0;
4555
4556 _rtw_memcpy(&type, dev_type, 2);
4557 type = be16_to_cpu(type);
4558 sprintf(dev_type_str, "\n\nN=%.2d", type);
4559 blnMatch = 1;
4560 }
4561 }
4562 break;
4563 }
4564
4565 plist = get_next(plist);
4566
4567 }
4568
4569 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4570
4571 if (!blnMatch)
4572 sprintf(dev_type_str, "\n\nN=00");
4573
4574 wrqu->data.length = strlen(dev_type_str);
4575 _rtw_memcpy(extra, dev_type_str, wrqu->data.length);
4576
4577 return ret;
4578
4579 }
4580
4581 static int rtw_p2p_get_device_name(struct net_device *dev,
4582 struct iw_request_info *info,
4583 union iwreq_data *wrqu, char *extra, char *subcmd)
4584 {
4585
4586 int ret = 0;
4587 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4588 u8 peerMAC[ETH_ALEN] = { 0x00 };
4589 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4590 _irqL irqL;
4591 _list *plist, *phead;
4592 _queue *queue = &(pmlmepriv->scanned_queue);
4593 struct wlan_network *pnetwork = NULL;
4594 u8 blnMatch = 0;
4595 u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = { 0x00 };
4596 uint dev_len = 0;
4597 u8 dev_name_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
4598
4599 /* Commented by Albert 20121225 */
4600 /* The input data is the MAC address which the application wants to know its device name. */
4601 /* Such user interface could show peer device's device name instead of ssid. */
4602 /* Format: iwpriv wlanx p2p_get2 devN=00:E0:4C:00:00:05 */
4603
4604 RTW_INFO("[%s] data = %s\n", __FUNCTION__, subcmd);
4605
4606 macstr2num(peerMAC, subcmd);
4607
4608 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4609
4610 phead = get_list_head(queue);
4611 plist = get_next(phead);
4612
4613 while (1) {
4614 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
4615 break;
4616
4617 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
4618 if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
4619 u8 *wpsie;
4620 uint wpsie_len = 0;
4621
4622 /* The mac address is matched. */
4623
4624 wpsie = rtw_get_wps_ie_from_scan_queue(&pnetwork->network.IEs[0], pnetwork->network.IELength, NULL, &wpsie_len, pnetwork->network.Reserved[0]);
4625 if (wpsie) {
4626 dev_len = sizeof(dev_name);
4627 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len);
4628 if (dev_len) {
4629 sprintf(dev_name_str, "\n\nN=%s", dev_name);
4630 blnMatch = 1;
4631 }
4632 }
4633 break;
4634 }
4635
4636 plist = get_next(plist);
4637
4638 }
4639
4640 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4641
4642 if (!blnMatch)
4643 sprintf(dev_name_str, "\n\nN=0000");
4644
4645 wrqu->data.length = strlen(dev_name_str);
4646 _rtw_memcpy(extra, dev_name_str, wrqu->data.length);
4647
4648 return ret;
4649
4650 }
4651
4652 static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
4653 struct iw_request_info *info,
4654 union iwreq_data *wrqu, char *extra, char *subcmd)
4655 {
4656
4657 int ret = 0;
4658 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4659 u8 peerMAC[ETH_ALEN] = { 0x00 };
4660 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4661 _irqL irqL;
4662 _list *plist, *phead;
4663 _queue *queue = &(pmlmepriv->scanned_queue);
4664 struct wlan_network *pnetwork = NULL;
4665 u8 blnMatch = 0;
4666 u8 *p2pie;
4667 uint p2pielen = 0, attr_contentlen = 2;
4668 u8 attr_content[2] = { 0x00 };
4669 u8 inv_proc_str[P2P_PRIVATE_IOCTL_SET_LEN] = { 0x00 };
4670
4671 /* Commented by Ouden 20121226 */
4672 /* The application wants to know P2P initation procedure is support or not. */
4673 /* Format: iwpriv wlanx p2p_get2 InvProc=00:E0:4C:00:00:05 */
4674
4675 RTW_INFO("[%s] data = %s\n", __FUNCTION__, subcmd);
4676
4677 macstr2num(peerMAC, subcmd);
4678
4679 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4680
4681 phead = get_list_head(queue);
4682 plist = get_next(phead);
4683
4684 while (1) {
4685 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
4686 break;
4687
4688 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
4689 if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
4690 /* Commented by Albert 20121226 */
4691 /* Match the device address located in the P2P IE */
4692 /* This is for the case that the P2P device address is not the same as the P2P interface address. */
4693
4694 p2pie = rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen);
4695 if (p2pie) {
4696 while (p2pie) {
4697 /* _rtw_memset( attr_content, 0x00, 2); */
4698 attr_contentlen = sizeof(attr_content);
4699 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_CAPABILITY, attr_content, &attr_contentlen)) {
4700 /* Handle the P2P capability attribute */
4701 blnMatch = 1;
4702 break;
4703
4704 }
4705
4706 /* Get the next P2P IE */
4707 p2pie = rtw_get_p2p_ie(p2pie + p2pielen, BSS_EX_TLV_IES_LEN(&pnetwork->network) - (p2pie + p2pielen - BSS_EX_TLV_IES(&pnetwork->network)), NULL, &p2pielen);
4708 }
4709 }
4710 }
4711
4712 plist = get_next(plist);
4713
4714 }
4715
4716 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4717
4718 if (!blnMatch)
4719 sprintf(inv_proc_str, "\nIP=-1");
4720 else {
4721 if ((attr_content[0] & 0x20) == 0x20)
4722 sprintf(inv_proc_str, "\nIP=1");
4723 else
4724 sprintf(inv_proc_str, "\nIP=0");
4725 }
4726
4727 wrqu->data.length = strlen(inv_proc_str);
4728 _rtw_memcpy(extra, inv_proc_str, wrqu->data.length);
4729
4730 return ret;
4731
4732 }
4733
4734 static int rtw_p2p_connect(struct net_device *dev,
4735 struct iw_request_info *info,
4736 union iwreq_data *wrqu, char *extra)
4737 {
4738
4739 int ret = 0;
4740 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4741 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4742 u8 peerMAC[ETH_ALEN] = { 0x00 };
4743 int jj, kk;
4744 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4745 _irqL irqL;
4746 _list *plist, *phead;
4747 _queue *queue = &(pmlmepriv->scanned_queue);
4748 struct wlan_network *pnetwork = NULL;
4749 uint uintPeerChannel = 0;
4750 #ifdef CONFIG_CONCURRENT_MODE
4751 struct roch_info *prochinfo = &padapter->rochinfo;
4752 #endif
4753
4754 /* Commented by Albert 20110304 */
4755 /* The input data contains two informations. */
4756 /* 1. First information is the MAC address which wants to formate with */
4757 /* 2. Second information is the WPS PINCode or "pbc" string for push button method */
4758 /* Format: 00:E0:4C:00:00:05 */
4759 /* Format: 00:E0:4C:00:00:05 */
4760
4761 RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
4762
4763 if (pwdinfo->p2p_state == P2P_STATE_NONE) {
4764 RTW_INFO("[%s] WiFi Direct is disable!\n", __FUNCTION__);
4765 return ret;
4766 }
4767
4768 if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO)
4769 return -1;
4770
4771 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
4772 peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
4773
4774 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4775
4776 phead = get_list_head(queue);
4777 plist = get_next(phead);
4778
4779 while (1) {
4780 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
4781 break;
4782
4783 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
4784 if (_rtw_memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
4785 if (pnetwork->network.Configuration.DSConfig != 0)
4786 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
4787 else if (pwdinfo->nego_req_info.peer_ch != 0)
4788 uintPeerChannel = pnetwork->network.Configuration.DSConfig = pwdinfo->nego_req_info.peer_ch;
4789 else {
4790 /* Unexpected case */
4791 uintPeerChannel = 0;
4792 RTW_INFO("%s uintPeerChannel = 0\n", __func__);
4793 }
4794 break;
4795 }
4796
4797 plist = get_next(plist);
4798
4799 }
4800
4801 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4802
4803 if (uintPeerChannel) {
4804 #ifdef CONFIG_CONCURRENT_MODE
4805 if (rtw_mi_check_status(padapter, MI_LINKED))
4806 _cancel_timer_ex(&prochinfo->ap_roch_ch_switch_timer);
4807 #endif /* CONFIG_CONCURRENT_MODE */
4808
4809 _rtw_memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
4810 _rtw_memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
4811
4812 pwdinfo->nego_req_info.peer_channel_num[0] = uintPeerChannel;
4813 _rtw_memcpy(pwdinfo->nego_req_info.peerDevAddr, pnetwork->network.MacAddress, ETH_ALEN);
4814 pwdinfo->nego_req_info.benable = _TRUE;
4815
4816 _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
4817 if (rtw_p2p_state(pwdinfo) != P2P_STATE_GONEGO_OK) {
4818 /* Restore to the listen state if the current p2p state is not nego OK */
4819 rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
4820 }
4821
4822 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
4823 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
4824
4825 #ifdef CONFIG_CONCURRENT_MODE
4826 if (rtw_mi_check_status(padapter, MI_LINKED)) {
4827 u8 union_ch = rtw_mi_get_union_chan(padapter);
4828 u8 union_bw = rtw_mi_get_union_bw(padapter);
4829 u8 union_offset = rtw_mi_get_union_offset(padapter);
4830
4831 set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
4832 rtw_leave_opch(padapter);
4833 }
4834 #endif /* CONFIG_CONCURRENT_MODE */
4835
4836 RTW_INFO("[%s] Start PreTx Procedure!\n", __FUNCTION__);
4837 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
4838 #ifdef CONFIG_CONCURRENT_MODE
4839 if (rtw_mi_check_status(padapter, MI_LINKED))
4840 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_GO_NEGO_TIMEOUT);
4841 else
4842 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT);
4843 #else
4844 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT);
4845 #endif /* CONFIG_CONCURRENT_MODE */
4846
4847 } else {
4848 RTW_INFO("[%s] Not Found in Scanning Queue~\n", __FUNCTION__);
4849 ret = -1;
4850 }
4851
4852 return ret;
4853 }
4854
4855 static int rtw_p2p_invite_req(struct net_device *dev,
4856 struct iw_request_info *info,
4857 union iwreq_data *wrqu, char *extra)
4858 {
4859
4860 int ret = 0;
4861 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
4862 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4863 int jj, kk;
4864 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4865 _list *plist, *phead;
4866 _queue *queue = &(pmlmepriv->scanned_queue);
4867 struct wlan_network *pnetwork = NULL;
4868 uint uintPeerChannel = 0;
4869 u8 attr_content[50] = { 0x00 };
4870 u8 *p2pie;
4871 uint p2pielen = 0, attr_contentlen = 50;
4872 _irqL irqL;
4873 struct tx_invite_req_info *pinvite_req_info = &pwdinfo->invitereq_info;
4874 #ifdef CONFIG_CONCURRENT_MODE
4875 struct roch_info *prochinfo = &padapter->rochinfo;
4876 #endif
4877
4878 /* Commented by Albert 20120321 */
4879 /* The input data contains two informations. */
4880 /* 1. First information is the P2P device address which you want to send to. */
4881 /* 2. Second information is the group id which combines with GO's mac address, space and GO's ssid. */
4882 /* Command line sample: iwpriv wlan0 p2p_set invite="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */
4883 /* Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy */
4884
4885 RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
4886
4887 if (wrqu->data.length <= 37) {
4888 RTW_INFO("[%s] Wrong format!\n", __FUNCTION__);
4889 return ret;
4890 }
4891
4892 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
4893 RTW_INFO("[%s] WiFi Direct is disable!\n", __FUNCTION__);
4894 return ret;
4895 } else {
4896 /* Reset the content of struct tx_invite_req_info */
4897 pinvite_req_info->benable = _FALSE;
4898 _rtw_memset(pinvite_req_info->go_bssid, 0x00, ETH_ALEN);
4899 _rtw_memset(pinvite_req_info->go_ssid, 0x00, WLAN_SSID_MAXLEN);
4900 pinvite_req_info->ssidlen = 0x00;
4901 pinvite_req_info->operating_ch = pwdinfo->operating_channel;
4902 _rtw_memset(pinvite_req_info->peer_macaddr, 0x00, ETH_ALEN);
4903 pinvite_req_info->token = 3;
4904 }
4905
4906 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
4907 pinvite_req_info->peer_macaddr[jj] = key_2char2num(extra[kk], extra[kk + 1]);
4908
4909 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4910
4911 phead = get_list_head(queue);
4912 plist = get_next(phead);
4913
4914 while (1) {
4915 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
4916 break;
4917
4918 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
4919
4920 /* Commented by Albert 2011/05/18 */
4921 /* Match the device address located in the P2P IE */
4922 /* This is for the case that the P2P device address is not the same as the P2P interface address. */
4923
4924 p2pie = rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen);
4925 if (p2pie) {
4926 /* The P2P Device ID attribute is included in the Beacon frame. */
4927 /* The P2P Device Info attribute is included in the probe response frame. */
4928
4929 attr_contentlen = sizeof(attr_content);
4930 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
4931 /* Handle the P2P Device ID attribute of Beacon first */
4932 if (_rtw_memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
4933 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
4934 break;
4935 }
4936 } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
4937 /* Handle the P2P Device Info attribute of probe response */
4938 if (_rtw_memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
4939 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
4940 break;
4941 }
4942 }
4943
4944 }
4945
4946 plist = get_next(plist);
4947
4948 }
4949
4950 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
4951
4952 #ifdef CONFIG_WFD
4953 if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST) && uintPeerChannel) {
4954 struct wifi_display_info *pwfd_info = pwdinfo->wfd_info;
4955 u8 *wfd_ie;
4956 uint wfd_ielen = 0;
4957
4958 wfd_ie = rtw_bss_ex_get_wfd_ie(&pnetwork->network, NULL, &wfd_ielen);
4959 if (wfd_ie) {
4960 u8 *wfd_devinfo;
4961 uint wfd_devlen;
4962
4963 RTW_INFO("[%s] Found WFD IE!\n", __FUNCTION__);
4964 wfd_devinfo = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, NULL, &wfd_devlen);
4965 if (wfd_devinfo) {
4966 u16 wfd_devinfo_field = 0;
4967
4968 /* Commented by Albert 20120319 */
4969 /* The first two bytes are the WFD device information field of WFD device information subelement. */
4970 /* In big endian format. */
4971 wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
4972 if (wfd_devinfo_field & WFD_DEVINFO_SESSION_AVAIL)
4973 pwfd_info->peer_session_avail = _TRUE;
4974 else
4975 pwfd_info->peer_session_avail = _FALSE;
4976 }
4977 }
4978
4979 if (_FALSE == pwfd_info->peer_session_avail) {
4980 RTW_INFO("[%s] WFD Session not avaiable!\n", __FUNCTION__);
4981 goto exit;
4982 }
4983 }
4984 #endif /* CONFIG_WFD */
4985
4986 if (uintPeerChannel) {
4987 #ifdef CONFIG_CONCURRENT_MODE
4988 if (rtw_mi_check_status(padapter, MI_LINKED))
4989 _cancel_timer_ex(&prochinfo->ap_roch_ch_switch_timer);
4990 #endif /* CONFIG_CONCURRENT_MODE */
4991
4992 /* Store the GO's bssid */
4993 for (jj = 0, kk = 18; jj < ETH_ALEN; jj++, kk += 3)
4994 pinvite_req_info->go_bssid[jj] = key_2char2num(extra[kk], extra[kk + 1]);
4995
4996 /* Store the GO's ssid */
4997 pinvite_req_info->ssidlen = wrqu->data.length - 36;
4998 _rtw_memcpy(pinvite_req_info->go_ssid, &extra[36], (u32) pinvite_req_info->ssidlen);
4999 pinvite_req_info->benable = _TRUE;
5000 pinvite_req_info->peer_ch = uintPeerChannel;
5001
5002 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
5003 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INVITE_REQ);
5004
5005 #ifdef CONFIG_CONCURRENT_MODE
5006 if (rtw_mi_check_status(padapter, MI_LINKED)) {
5007 u8 union_ch = rtw_mi_get_union_chan(padapter);
5008 u8 union_bw = rtw_mi_get_union_bw(padapter);
5009 u8 union_offset = rtw_mi_get_union_offset(padapter);
5010
5011 set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
5012 rtw_leave_opch(padapter);
5013
5014 } else
5015 set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
5016 #else
5017 set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
5018 #endif/*CONFIG_CONCURRENT_MODE*/
5019
5020 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
5021
5022 #ifdef CONFIG_CONCURRENT_MODE
5023 if (rtw_mi_check_status(padapter, MI_LINKED))
5024 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_INVITE_TIMEOUT);
5025 else
5026 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT);
5027 #else
5028 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT);
5029 #endif /* CONFIG_CONCURRENT_MODE */
5030
5031
5032 } else
5033 RTW_INFO("[%s] NOT Found in the Scanning Queue!\n", __FUNCTION__);
5034 exit:
5035
5036 return ret;
5037
5038 }
5039
5040 static int rtw_p2p_set_persistent(struct net_device *dev,
5041 struct iw_request_info *info,
5042 union iwreq_data *wrqu, char *extra)
5043 {
5044
5045 int ret = 0;
5046 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5047 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
5048
5049 /* Commented by Albert 20120328 */
5050 /* The input data is 0 or 1 */
5051 /* 0: disable persistent group functionality */
5052 /* 1: enable persistent group founctionality */
5053
5054 RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
5055
5056 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
5057 RTW_INFO("[%s] WiFi Direct is disable!\n", __FUNCTION__);
5058 return ret;
5059 } else {
5060 if (extra[0] == '0') /* Disable the persistent group function. */
5061 pwdinfo->persistent_supported = _FALSE;
5062 else if (extra[0] == '1') /* Enable the persistent group function. */
5063 pwdinfo->persistent_supported = _TRUE;
5064 else
5065 pwdinfo->persistent_supported = _FALSE;
5066 }
5067 printk("[%s] persistent_supported = %d\n", __FUNCTION__, pwdinfo->persistent_supported);
5068
5069 return ret;
5070
5071 }
5072
5073 static int uuid_str2bin(const char *str, u8 *bin)
5074 {
5075 const char *pos;
5076 u8 *opos;
5077
5078 pos = str;
5079 opos = bin;
5080
5081 if (hexstr2bin(pos, opos, 4))
5082 return -1;
5083 pos += 8;
5084 opos += 4;
5085
5086 if (*pos++ != '-' || hexstr2bin(pos, opos, 2))
5087 return -1;
5088 pos += 4;
5089 opos += 2;
5090
5091 if (*pos++ != '-' || hexstr2bin(pos, opos, 2))
5092 return -1;
5093 pos += 4;
5094 opos += 2;
5095
5096 if (*pos++ != '-' || hexstr2bin(pos, opos, 2))
5097 return -1;
5098 pos += 4;
5099 opos += 2;
5100
5101 if (*pos++ != '-' || hexstr2bin(pos, opos, 6))
5102 return -1;
5103
5104 return 0;
5105 }
5106
5107 static int rtw_p2p_set_wps_uuid(struct net_device *dev,
5108 struct iw_request_info *info,
5109 union iwreq_data *wrqu, char *extra)
5110 {
5111
5112 int ret = 0;
5113 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5114 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
5115
5116 RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
5117
5118 if ((36 == strlen(extra)) && (uuid_str2bin(extra, pwdinfo->uuid) == 0))
5119 pwdinfo->external_uuid = 1;
5120 else {
5121 pwdinfo->external_uuid = 0;
5122 ret = -EINVAL;
5123 }
5124
5125 return ret;
5126
5127 }
5128 #ifdef CONFIG_WFD
5129 static int rtw_p2p_set_pc(struct net_device *dev,
5130 struct iw_request_info *info,
5131 union iwreq_data *wrqu, char *extra)
5132 {
5133
5134 int ret = 0;
5135 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5136 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
5137 u8 peerMAC[ETH_ALEN] = { 0x00 };
5138 int jj, kk;
5139 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5140 _list *plist, *phead;
5141 _queue *queue = &(pmlmepriv->scanned_queue);
5142 struct wlan_network *pnetwork = NULL;
5143 u8 attr_content[50] = { 0x00 };
5144 u8 *p2pie;
5145 uint p2pielen = 0, attr_contentlen = 50;
5146 _irqL irqL;
5147 uint uintPeerChannel = 0;
5148
5149 struct wifi_display_info *pwfd_info = pwdinfo->wfd_info;
5150
5151 /* Commented by Albert 20120512 */
5152 /* 1. Input information is the MAC address which wants to know the Preferred Connection bit (PC bit) */
5153 /* Format: 00:E0:4C:00:00:05 */
5154
5155 RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
5156
5157 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
5158 RTW_INFO("[%s] WiFi Direct is disable!\n", __FUNCTION__);
5159 return ret;
5160 }
5161
5162 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
5163 peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
5164
5165 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5166
5167 phead = get_list_head(queue);
5168 plist = get_next(phead);
5169
5170 while (1) {
5171 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
5172 break;
5173
5174 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
5175
5176 /* Commented by Albert 2011/05/18 */
5177 /* Match the device address located in the P2P IE */
5178 /* This is for the case that the P2P device address is not the same as the P2P interface address. */
5179
5180 p2pie = rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen);
5181 if (p2pie) {
5182 /* The P2P Device ID attribute is included in the Beacon frame. */
5183 /* The P2P Device Info attribute is included in the probe response frame. */
5184 printk("[%s] Got P2P IE\n", __FUNCTION__);
5185 attr_contentlen = sizeof(attr_content);
5186 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
5187 /* Handle the P2P Device ID attribute of Beacon first */
5188 printk("[%s] P2P_ATTR_DEVICE_ID\n", __FUNCTION__);
5189 if (_rtw_memcmp(attr_content, peerMAC, ETH_ALEN)) {
5190 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
5191 break;
5192 }
5193 } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
5194 /* Handle the P2P Device Info attribute of probe response */
5195 printk("[%s] P2P_ATTR_DEVICE_INFO\n", __FUNCTION__);
5196 if (_rtw_memcmp(attr_content, peerMAC, ETH_ALEN)) {
5197 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
5198 break;
5199 }
5200 }
5201
5202 }
5203
5204 plist = get_next(plist);
5205
5206 }
5207
5208 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5209 printk("[%s] channel = %d\n", __FUNCTION__, uintPeerChannel);
5210
5211 if (uintPeerChannel) {
5212 u8 *wfd_ie;
5213 uint wfd_ielen = 0;
5214
5215 wfd_ie = rtw_bss_ex_get_wfd_ie(&pnetwork->network, NULL, &wfd_ielen);
5216 if (wfd_ie) {
5217 u8 *wfd_devinfo;
5218 uint wfd_devlen;
5219
5220 RTW_INFO("[%s] Found WFD IE!\n", __FUNCTION__);
5221 wfd_devinfo = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, NULL, &wfd_devlen);
5222 if (wfd_devinfo) {
5223 u16 wfd_devinfo_field = 0;
5224
5225 /* Commented by Albert 20120319 */
5226 /* The first two bytes are the WFD device information field of WFD device information subelement. */
5227 /* In big endian format. */
5228 wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
5229 if (wfd_devinfo_field & WFD_DEVINFO_PC_TDLS)
5230 pwfd_info->wfd_pc = _TRUE;
5231 else
5232 pwfd_info->wfd_pc = _FALSE;
5233 }
5234 }
5235 } else
5236 RTW_INFO("[%s] NOT Found in the Scanning Queue!\n", __FUNCTION__);
5237
5238 return ret;
5239
5240 }
5241
5242 static int rtw_p2p_set_wfd_device_type(struct net_device *dev,
5243 struct iw_request_info *info,
5244 union iwreq_data *wrqu, char *extra)
5245 {
5246
5247 int ret = 0;
5248 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5249 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
5250 struct wifi_display_info *pwfd_info = pwdinfo->wfd_info;
5251
5252 /* Commented by Albert 20120328 */
5253 /* The input data is 0 or 1 */
5254 /* 0: specify to Miracast source device */
5255 /* 1 or others: specify to Miracast sink device (display device) */
5256
5257 RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
5258
5259 if (extra[0] == '0') /* Set to Miracast source device. */
5260 pwfd_info->wfd_device_type = WFD_DEVINFO_SOURCE;
5261 else /* Set to Miracast sink device. */
5262 pwfd_info->wfd_device_type = WFD_DEVINFO_PSINK;
5263
5264 return ret;
5265
5266 }
5267
5268 static int rtw_p2p_set_wfd_enable(struct net_device *dev,
5269 struct iw_request_info *info,
5270 union iwreq_data *wrqu, char *extra)
5271 {
5272 /* Commented by Kurt 20121206
5273 * This function is used to set wfd enabled */
5274
5275 int ret = 0;
5276 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5277 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
5278
5279 if (*extra == '0')
5280 rtw_wfd_enable(padapter, 0);
5281 else if (*extra == '1')
5282 rtw_wfd_enable(padapter, 1);
5283
5284 RTW_INFO("[%s] wfd_enable = %d\n", __FUNCTION__, pwdinfo->wfd_info->wfd_enable);
5285
5286 return ret;
5287
5288 }
5289
5290 static int rtw_p2p_set_driver_iface(struct net_device *dev,
5291 struct iw_request_info *info,
5292 union iwreq_data *wrqu, char *extra)
5293 {
5294 /* Commented by Kurt 20121206
5295 * This function is used to set driver iface is WEXT or CFG80211 */
5296 int ret = 0;
5297 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5298 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
5299
5300 if (*extra == '1') {
5301 pwdinfo->driver_interface = DRIVER_WEXT;
5302 RTW_INFO("[%s] driver_interface = WEXT\n", __FUNCTION__);
5303 } else if (*extra == '2') {
5304 pwdinfo->driver_interface = DRIVER_CFG80211;
5305 RTW_INFO("[%s] driver_interface = CFG80211\n", __FUNCTION__);
5306 }
5307
5308 return ret;
5309
5310 }
5311
5312 /* To set the WFD session available to enable or disable */
5313 static int rtw_p2p_set_sa(struct net_device *dev,
5314 struct iw_request_info *info,
5315 union iwreq_data *wrqu, char *extra)
5316 {
5317
5318 int ret = 0;
5319 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5320 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
5321
5322 RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
5323
5324 if (0) {
5325 RTW_INFO("[%s] WiFi Direct is disable!\n", __FUNCTION__);
5326 return ret;
5327 } else {
5328 if (extra[0] == '0') /* Disable the session available. */
5329 pwdinfo->session_available = _FALSE;
5330 else if (extra[0] == '1') /* Enable the session available. */
5331 pwdinfo->session_available = _TRUE;
5332 else
5333 pwdinfo->session_available = _FALSE;
5334 }
5335 printk("[%s] session available = %d\n", __FUNCTION__, pwdinfo->session_available);
5336
5337 return ret;
5338
5339 }
5340 #endif /* CONFIG_WFD */
5341
5342 static int rtw_p2p_prov_disc(struct net_device *dev,
5343 struct iw_request_info *info,
5344 union iwreq_data *wrqu, char *extra)
5345 {
5346 int ret = 0;
5347 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5348 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
5349 u8 peerMAC[ETH_ALEN] = { 0x00 };
5350 int jj, kk;
5351 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5352 _list *plist, *phead;
5353 _queue *queue = &(pmlmepriv->scanned_queue);
5354 struct wlan_network *pnetwork = NULL;
5355 uint uintPeerChannel = 0;
5356 u8 attr_content[100] = { 0x00 };
5357 u8 *p2pie;
5358 uint p2pielen = 0, attr_contentlen = 100;
5359 _irqL irqL;
5360 #ifdef CONFIG_CONCURRENT_MODE
5361 struct roch_info *prochinfo = &padapter->rochinfo;
5362 #endif
5363
5364 /* Commented by Albert 20110301 */
5365 /* The input data contains two informations. */
5366 /* 1. First information is the MAC address which wants to issue the provisioning discovery request frame. */
5367 /* 2. Second information is the WPS configuration method which wants to discovery */
5368 /* Format: 00:E0:4C:00:00:05_display */
5369 /* Format: 00:E0:4C:00:00:05_keypad */
5370 /* Format: 00:E0:4C:00:00:05_pbc */
5371 /* Format: 00:E0:4C:00:00:05_label */
5372
5373 RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
5374
5375 if (pwdinfo->p2p_state == P2P_STATE_NONE) {
5376 RTW_INFO("[%s] WiFi Direct is disable!\n", __FUNCTION__);
5377 return ret;
5378 } else {
5379 /* Reset the content of struct tx_provdisc_req_info excluded the wps_config_method_request. */
5380 _rtw_memset(pwdinfo->tx_prov_disc_info.peerDevAddr, 0x00, ETH_ALEN);
5381 _rtw_memset(pwdinfo->tx_prov_disc_info.peerIFAddr, 0x00, ETH_ALEN);
5382 _rtw_memset(&pwdinfo->tx_prov_disc_info.ssid, 0x00, sizeof(NDIS_802_11_SSID));
5383 pwdinfo->tx_prov_disc_info.peer_channel_num[0] = 0;
5384 pwdinfo->tx_prov_disc_info.peer_channel_num[1] = 0;
5385 pwdinfo->tx_prov_disc_info.benable = _FALSE;
5386 }
5387
5388 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
5389 peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
5390
5391 if (_rtw_memcmp(&extra[18], "display", 7))
5392 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA;
5393 else if (_rtw_memcmp(&extra[18], "keypad", 7))
5394 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD;
5395 else if (_rtw_memcmp(&extra[18], "pbc", 3))
5396 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
5397 else if (_rtw_memcmp(&extra[18], "label", 5))
5398 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL;
5399 else {
5400 RTW_INFO("[%s] Unknown WPS config methodn", __FUNCTION__);
5401 return ret ;
5402 }
5403
5404 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5405
5406 phead = get_list_head(queue);
5407 plist = get_next(phead);
5408
5409 while (1) {
5410 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
5411 break;
5412
5413 if (uintPeerChannel != 0)
5414 break;
5415
5416 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
5417
5418 /* Commented by Albert 2011/05/18 */
5419 /* Match the device address located in the P2P IE */
5420 /* This is for the case that the P2P device address is not the same as the P2P interface address. */
5421
5422 p2pie = rtw_bss_ex_get_p2p_ie(&pnetwork->network, NULL, &p2pielen);
5423 if (p2pie) {
5424 while (p2pie) {
5425 /* The P2P Device ID attribute is included in the Beacon frame. */
5426 /* The P2P Device Info attribute is included in the probe response frame. */
5427 attr_contentlen = sizeof(attr_content);
5428 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
5429 /* Handle the P2P Device ID attribute of Beacon first */
5430 if (_rtw_memcmp(attr_content, peerMAC, ETH_ALEN)) {
5431 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
5432 break;
5433 }
5434 } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
5435 /* Handle the P2P Device Info attribute of probe response */
5436 if (_rtw_memcmp(attr_content, peerMAC, ETH_ALEN)) {
5437 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
5438 break;
5439 }
5440 }
5441
5442 /* Get the next P2P IE */
5443 p2pie = rtw_get_p2p_ie(p2pie + p2pielen, BSS_EX_TLV_IES_LEN(&pnetwork->network) - (p2pie + p2pielen - BSS_EX_TLV_IES(&pnetwork->network)), NULL, &p2pielen);
5444 }
5445
5446 }
5447
5448 plist = get_next(plist);
5449
5450 }
5451
5452 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
5453
5454 if (uintPeerChannel) {
5455 #ifdef CONFIG_WFD
5456 if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
5457 struct wifi_display_info *pwfd_info = pwdinfo->wfd_info;
5458 u8 *wfd_ie;
5459 uint wfd_ielen = 0;
5460
5461 wfd_ie = rtw_bss_ex_get_wfd_ie(&pnetwork->network, NULL, &wfd_ielen);
5462 if (wfd_ie) {
5463 u8 *wfd_devinfo;
5464 uint wfd_devlen;
5465
5466 RTW_INFO("[%s] Found WFD IE!\n", __FUNCTION__);
5467 wfd_devinfo = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, NULL, &wfd_devlen);
5468 if (wfd_devinfo) {
5469 u16 wfd_devinfo_field = 0;
5470
5471 /* Commented by Albert 20120319 */
5472 /* The first two bytes are the WFD device information field of WFD device information subelement. */
5473 /* In big endian format. */
5474 wfd_devinfo_field = RTW_GET_BE16(wfd_devinfo);
5475 if (wfd_devinfo_field & WFD_DEVINFO_SESSION_AVAIL)
5476 pwfd_info->peer_session_avail = _TRUE;
5477 else
5478 pwfd_info->peer_session_avail = _FALSE;
5479 }
5480 }
5481
5482 if (_FALSE == pwfd_info->peer_session_avail) {
5483 RTW_INFO("[%s] WFD Session not avaiable!\n", __FUNCTION__);
5484 goto exit;
5485 }
5486 }
5487 #endif /* CONFIG_WFD */
5488
5489 RTW_INFO("[%s] peer channel: %d!\n", __FUNCTION__, uintPeerChannel);
5490 #ifdef CONFIG_CONCURRENT_MODE
5491 if (rtw_mi_check_status(padapter, MI_LINKED))
5492 _cancel_timer_ex(&prochinfo->ap_roch_ch_switch_timer);
5493 #endif /* CONFIG_CONCURRENT_MODE */
5494 _rtw_memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, pnetwork->network.MacAddress, ETH_ALEN);
5495 _rtw_memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, peerMAC, ETH_ALEN);
5496 pwdinfo->tx_prov_disc_info.peer_channel_num[0] = (u16) uintPeerChannel;
5497 pwdinfo->tx_prov_disc_info.benable = _TRUE;
5498 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
5499 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ);
5500
5501 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT))
5502 _rtw_memcpy(&pwdinfo->tx_prov_disc_info.ssid, &pnetwork->network.Ssid, sizeof(NDIS_802_11_SSID));
5503 else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
5504 _rtw_memcpy(pwdinfo->tx_prov_disc_info.ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
5505 pwdinfo->tx_prov_disc_info.ssid.SsidLength = P2P_WILDCARD_SSID_LEN;
5506 }
5507
5508 #ifdef CONFIG_CONCURRENT_MODE
5509 if (rtw_mi_check_status(padapter, MI_LINKED)) {
5510 u8 union_ch = rtw_mi_get_union_chan(padapter);
5511 u8 union_bw = rtw_mi_get_union_bw(padapter);
5512 u8 union_offset = rtw_mi_get_union_offset(padapter);
5513
5514 set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
5515 rtw_leave_opch(padapter);
5516
5517 } else
5518 set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
5519 #else
5520 set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
5521 #endif
5522
5523 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
5524
5525 #ifdef CONFIG_CONCURRENT_MODE
5526 if (rtw_mi_check_status(padapter, MI_LINKED))
5527 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_CONCURRENT_PROVISION_TIMEOUT);
5528 else
5529 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
5530 #else
5531 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
5532 #endif /* CONFIG_CONCURRENT_MODE */
5533
5534 } else {
5535 RTW_INFO("[%s] NOT Found in the Scanning Queue!\n", __FUNCTION__);
5536 }
5537 exit:
5538
5539 return ret;
5540
5541 }
5542
5543 /* Added by Albert 20110328
5544 * This function is used to inform the driver the user had specified the pin code value or pbc
5545 * to application. */
5546
5547 static int rtw_p2p_got_wpsinfo(struct net_device *dev,
5548 struct iw_request_info *info,
5549 union iwreq_data *wrqu, char *extra)
5550 {
5551
5552 int ret = 0;
5553 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5554 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
5555
5556
5557 RTW_INFO("[%s] data = %s\n", __FUNCTION__, extra);
5558 /* Added by Albert 20110328 */
5559 /* if the input data is P2P_NO_WPSINFO -> reset the wpsinfo */
5560 /* if the input data is P2P_GOT_WPSINFO_PEER_DISPLAY_PIN -> the utility just input the PIN code got from the peer P2P device. */
5561 /* if the input data is P2P_GOT_WPSINFO_SELF_DISPLAY_PIN -> the utility just got the PIN code from itself. */
5562 /* if the input data is P2P_GOT_WPSINFO_PBC -> the utility just determine to use the PBC */
5563
5564 if (*extra == '0')
5565 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
5566 else if (*extra == '1')
5567 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PEER_DISPLAY_PIN;
5568 else if (*extra == '2')
5569 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_SELF_DISPLAY_PIN;
5570 else if (*extra == '3')
5571 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PBC;
5572 else
5573 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
5574
5575 return ret;
5576
5577 }
5578
5579 #endif /* CONFIG_P2P */
5580
5581 static int rtw_p2p_set(struct net_device *dev,
5582 struct iw_request_info *info,
5583 union iwreq_data *wrqu, char *extra)
5584 {
5585 int ret = 0;
5586 #ifdef CONFIG_P2P
5587 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5588
5589 RTW_INFO("[%s] extra = %s\n", __FUNCTION__, extra);
5590
5591 if (_rtw_memcmp(extra, "enable=", 7))
5592 rtw_wext_p2p_enable(dev, info, wrqu, &extra[7]);
5593 else if (_rtw_memcmp(extra, "setDN=", 6)) {
5594 wrqu->data.length -= 6;
5595 rtw_p2p_setDN(dev, info, wrqu, &extra[6]);
5596 } else if (_rtw_memcmp(extra, "profilefound=", 13)) {
5597 wrqu->data.length -= 13;
5598 rtw_p2p_profilefound(dev, info, wrqu, &extra[13]);
5599 } else if (_rtw_memcmp(extra, "prov_disc=", 10)) {
5600 wrqu->data.length -= 10;
5601 rtw_p2p_prov_disc(dev, info, wrqu, &extra[10]);
5602 } else if (_rtw_memcmp(extra, "nego=", 5)) {
5603 wrqu->data.length -= 5;
5604 rtw_p2p_connect(dev, info, wrqu, &extra[5]);
5605 } else if (_rtw_memcmp(extra, "intent=", 7)) {
5606 /* Commented by Albert 2011/03/23 */
5607 /* The wrqu->data.length will include the null character */
5608 /* So, we will decrease 7 + 1 */
5609 wrqu->data.length -= 8;
5610 rtw_p2p_set_intent(dev, info, wrqu, &extra[7]);
5611 } else if (_rtw_memcmp(extra, "ssid=", 5)) {
5612 wrqu->data.length -= 5;
5613 rtw_p2p_set_go_nego_ssid(dev, info, wrqu, &extra[5]);
5614 } else if (_rtw_memcmp(extra, "got_wpsinfo=", 12)) {
5615 wrqu->data.length -= 12;
5616 rtw_p2p_got_wpsinfo(dev, info, wrqu, &extra[12]);
5617 } else if (_rtw_memcmp(extra, "listen_ch=", 10)) {
5618 /* Commented by Albert 2011/05/24 */
5619 /* The wrqu->data.length will include the null character */
5620 /* So, we will decrease (10 + 1) */
5621 wrqu->data.length -= 11;
5622 rtw_p2p_set_listen_ch(dev, info, wrqu, &extra[10]);
5623 } else if (_rtw_memcmp(extra, "op_ch=", 6)) {
5624 /* Commented by Albert 2011/05/24 */
5625 /* The wrqu->data.length will include the null character */
5626 /* So, we will decrease (6 + 1) */
5627 wrqu->data.length -= 7;
5628 rtw_p2p_set_op_ch(dev, info, wrqu, &extra[6]);
5629 } else if (_rtw_memcmp(extra, "invite=", 7)) {
5630 wrqu->data.length -= 8;
5631 rtw_p2p_invite_req(dev, info, wrqu, &extra[7]);
5632 } else if (_rtw_memcmp(extra, "persistent=", 11)) {
5633 wrqu->data.length -= 11;
5634 rtw_p2p_set_persistent(dev, info, wrqu, &extra[11]);
5635 } else if (_rtw_memcmp(extra, "uuid=", 5)) {
5636 wrqu->data.length -= 5;
5637 ret = rtw_p2p_set_wps_uuid(dev, info, wrqu, &extra[5]);
5638 }
5639
5640 #ifdef CONFIG_WFD
5641 if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
5642 if (_rtw_memcmp(extra, "sa=", 3)) {
5643 /* sa: WFD Session Available information */
5644 wrqu->data.length -= 3;
5645 rtw_p2p_set_sa(dev, info, wrqu, &extra[3]);
5646 } else if (_rtw_memcmp(extra, "pc=", 3)) {
5647 /* pc: WFD Preferred Connection */
5648 wrqu->data.length -= 3;
5649 rtw_p2p_set_pc(dev, info, wrqu, &extra[3]);
5650 } else if (_rtw_memcmp(extra, "wfd_type=", 9)) {
5651 wrqu->data.length -= 9;
5652 rtw_p2p_set_wfd_device_type(dev, info, wrqu, &extra[9]);
5653 } else if (_rtw_memcmp(extra, "wfd_enable=", 11)) {
5654 wrqu->data.length -= 11;
5655 rtw_p2p_set_wfd_enable(dev, info, wrqu, &extra[11]);
5656 } else if (_rtw_memcmp(extra, "driver_iface=", 13)) {
5657 wrqu->data.length -= 13;
5658 rtw_p2p_set_driver_iface(dev, info, wrqu, &extra[13]);
5659 }
5660 }
5661 #endif /* CONFIG_WFD */
5662
5663 #endif /* CONFIG_P2P */
5664
5665 return ret;
5666
5667 }
5668
5669 static int rtw_p2p_get(struct net_device *dev,
5670 struct iw_request_info *info,
5671 union iwreq_data *wrqu, char *extra)
5672 {
5673 int ret = 0;
5674 #ifdef CONFIG_P2P
5675 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5676
5677 if (padapter->bShowGetP2PState)
5678 RTW_INFO("[%s] extra = %s\n", __FUNCTION__, (char *) wrqu->data.pointer);
5679
5680 if (_rtw_memcmp(wrqu->data.pointer, "status", 6))
5681 rtw_p2p_get_status(dev, info, wrqu, extra);
5682 else if (_rtw_memcmp(wrqu->data.pointer, "role", 4))
5683 rtw_p2p_get_role(dev, info, wrqu, extra);
5684 else if (_rtw_memcmp(wrqu->data.pointer, "peer_ifa", 8))
5685 rtw_p2p_get_peer_ifaddr(dev, info, wrqu, extra);
5686 else if (_rtw_memcmp(wrqu->data.pointer, "req_cm", 6))
5687 rtw_p2p_get_req_cm(dev, info, wrqu, extra);
5688 else if (_rtw_memcmp(wrqu->data.pointer, "peer_deva", 9)) {
5689 /* Get the P2P device address when receiving the provision discovery request frame. */
5690 rtw_p2p_get_peer_devaddr(dev, info, wrqu, extra);
5691 } else if (_rtw_memcmp(wrqu->data.pointer, "group_id", 8))
5692 rtw_p2p_get_groupid(dev, info, wrqu, extra);
5693 else if (_rtw_memcmp(wrqu->data.pointer, "inv_peer_deva", 13)) {
5694 /* Get the P2P device address when receiving the P2P Invitation request frame. */
5695 rtw_p2p_get_peer_devaddr_by_invitation(dev, info, wrqu, extra);
5696 } else if (_rtw_memcmp(wrqu->data.pointer, "op_ch", 5))
5697 rtw_p2p_get_op_ch(dev, info, wrqu, extra);
5698
5699 #ifdef CONFIG_WFD
5700 if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
5701 if (_rtw_memcmp(wrqu->data.pointer, "peer_port", 9))
5702 rtw_p2p_get_peer_wfd_port(dev, info, wrqu, extra);
5703 else if (_rtw_memcmp(wrqu->data.pointer, "wfd_sa", 6))
5704 rtw_p2p_get_peer_wfd_session_available(dev, info, wrqu, extra);
5705 else if (_rtw_memcmp(wrqu->data.pointer, "wfd_pc", 6))
5706 rtw_p2p_get_peer_wfd_preferred_connection(dev, info, wrqu, extra);
5707 }
5708 #endif /* CONFIG_WFD */
5709
5710 #endif /* CONFIG_P2P */
5711
5712 return ret;
5713
5714 }
5715
5716 static int rtw_p2p_get2(struct net_device *dev,
5717 struct iw_request_info *info,
5718 union iwreq_data *wrqu, char *extra)
5719 {
5720
5721 int ret = 0;
5722
5723 #ifdef CONFIG_P2P
5724
5725 int length = wrqu->data.length;
5726 char *buffer = (u8 *)rtw_malloc(length);
5727
5728 if (buffer == NULL) {
5729 ret = -ENOMEM;
5730 goto bad;
5731 }
5732
5733 if (copy_from_user(buffer, wrqu->data.pointer, wrqu->data.length)) {
5734 ret = -EFAULT;
5735 goto bad;
5736 }
5737
5738 RTW_INFO("[%s] buffer = %s\n", __FUNCTION__, buffer);
5739
5740 if (_rtw_memcmp(buffer, "wpsCM=", 6))
5741 ret = rtw_p2p_get_wps_configmethod(dev, info, wrqu, extra, &buffer[6]);
5742 else if (_rtw_memcmp(buffer, "devN=", 5))
5743 ret = rtw_p2p_get_device_name(dev, info, wrqu, extra, &buffer[5]);
5744 else if (_rtw_memcmp(buffer, "dev_type=", 9))
5745 ret = rtw_p2p_get_device_type(dev, info, wrqu, extra, &buffer[9]);
5746 else if (_rtw_memcmp(buffer, "go_devadd=", 10))
5747 ret = rtw_p2p_get_go_device_address(dev, info, wrqu, extra, &buffer[10]);
5748 else if (_rtw_memcmp(buffer, "InvProc=", 8))
5749 ret = rtw_p2p_get_invitation_procedure(dev, info, wrqu, extra, &buffer[8]);
5750 else {
5751 snprintf(extra, sizeof("Command not found."), "Command not found.");
5752 wrqu->data.length = strlen(extra);
5753 }
5754
5755 bad:
5756 if (buffer)
5757 rtw_mfree(buffer, length);
5758
5759 #endif /* CONFIG_P2P */
5760
5761 return ret;
5762
5763 }
5764
5765 #ifdef CONFIG_MP_INCLUDED
5766 static int rtw_cta_test_start(struct net_device *dev,
5767 struct iw_request_info *info,
5768 union iwreq_data *wrqu, char *extra)
5769 {
5770 int ret = 0;
5771 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5772 HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter);
5773
5774 RTW_INFO("%s %s\n", __func__, extra);
5775 if (!strcmp(extra, "1"))
5776 hal_data->in_cta_test = 1;
5777 else
5778 hal_data->in_cta_test = 0;
5779
5780 rtw_hal_rcr_set_chk_bssid(padapter, MLME_ACTION_NONE);
5781
5782 return ret;
5783 }
5784 #endif
5785 extern int rtw_change_ifname(_adapter *padapter, const char *ifname);
5786 static int rtw_rereg_nd_name(struct net_device *dev,
5787 struct iw_request_info *info,
5788 union iwreq_data *wrqu, char *extra)
5789 {
5790 int ret = 0;
5791 _adapter *padapter = rtw_netdev_priv(dev);
5792 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
5793 struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv;
5794 char new_ifname[IFNAMSIZ];
5795
5796 if (rereg_priv->old_ifname[0] == 0) {
5797 char *reg_ifname;
5798 #ifdef CONFIG_CONCURRENT_MODE
5799 if (padapter->isprimary)
5800 reg_ifname = padapter->registrypriv.ifname;
5801 else
5802 #endif
5803 reg_ifname = padapter->registrypriv.if2name;
5804
5805 strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ);
5806 rereg_priv->old_ifname[IFNAMSIZ - 1] = 0;
5807 }
5808
5809 /* RTW_INFO("%s wrqu->data.length:%d\n", __FUNCTION__, wrqu->data.length); */
5810 if (wrqu->data.length > IFNAMSIZ)
5811 return -EFAULT;
5812
5813 if (copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ))
5814 return -EFAULT;
5815
5816 if (0 == strcmp(rereg_priv->old_ifname, new_ifname))
5817 return ret;
5818
5819 RTW_INFO("%s new_ifname:%s\n", __FUNCTION__, new_ifname);
5820 rtw_set_rtnl_lock_holder(dvobj, current);
5821 ret = rtw_change_ifname(padapter, new_ifname);
5822 rtw_set_rtnl_lock_holder(dvobj, NULL);
5823 if (0 != ret)
5824 goto exit;
5825
5826 if (_rtw_memcmp(rereg_priv->old_ifname, "disable%d", 9) == _TRUE) {
5827 /* rtw_ips_mode_req(&padapter->pwrctrlpriv, rereg_priv->old_ips_mode); */
5828 }
5829
5830 strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
5831 rereg_priv->old_ifname[IFNAMSIZ - 1] = 0;
5832
5833 if (_rtw_memcmp(new_ifname, "disable%d", 9) == _TRUE) {
5834
5835 RTW_INFO("%s disable\n", __FUNCTION__);
5836 /* free network queue for Android's timming issue */
5837 rtw_free_network_queue(padapter, _TRUE);
5838
5839 /* the interface is being "disabled", we can do deeper IPS */
5840 /* rereg_priv->old_ips_mode = rtw_get_ips_mode_req(&padapter->pwrctrlpriv); */
5841 /* rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL); */
5842 }
5843 exit:
5844 return ret;
5845
5846 }
5847
5848 #ifdef CONFIG_IOL
5849 #include <rtw_iol.h>
5850 #endif
5851 #ifdef CONFIG_BACKGROUND_NOISE_MONITOR
5852 #include "../../hal/hal_dm_acs.h"
5853 #endif
5854 #ifdef DBG_CMD_QUEUE
5855 u8 dump_cmd_id = 0;
5856 #endif
5857
5858 static int rtw_dbg_port(struct net_device *dev,
5859 struct iw_request_info *info,
5860 union iwreq_data *wrqu, char *extra)
5861 {
5862 int ret = 0;
5863 #ifdef CONFIG_RTW_DEBUG
5864 _irqL irqL;
5865 u8 major_cmd, minor_cmd;
5866 u16 arg;
5867 u32 extra_arg, *pdata, val32;
5868 struct sta_info *psta;
5869 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
5870 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5871 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5872 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5873 struct security_priv *psecuritypriv = &padapter->securitypriv;
5874 struct wlan_network *cur_network = &(pmlmepriv->cur_network);
5875 struct sta_priv *pstapriv = &padapter->stapriv;
5876
5877
5878 pdata = (u32 *)&wrqu->data;
5879
5880 val32 = *pdata;
5881 arg = (u16)(val32 & 0x0000ffff);
5882 major_cmd = (u8)(val32 >> 24);
5883 minor_cmd = (u8)((val32 >> 16) & 0x00ff);
5884
5885 extra_arg = *(pdata + 1);
5886
5887 switch (major_cmd) {
5888 case 0x70: /* read_reg */
5889 switch (minor_cmd) {
5890 case 1:
5891 RTW_INFO("rtw_read8(0x%x)=0x%02x\n", arg, rtw_read8(padapter, arg));
5892 break;
5893 case 2:
5894 RTW_INFO("rtw_read16(0x%x)=0x%04x\n", arg, rtw_read16(padapter, arg));
5895 break;
5896 case 4:
5897 RTW_INFO("rtw_read32(0x%x)=0x%08x\n", arg, rtw_read32(padapter, arg));
5898 break;
5899 }
5900 break;
5901 case 0x71: /* write_reg */
5902 switch (minor_cmd) {
5903 case 1:
5904 rtw_write8(padapter, arg, extra_arg);
5905 RTW_INFO("rtw_write8(0x%x)=0x%02x\n", arg, rtw_read8(padapter, arg));
5906 break;
5907 case 2:
5908 rtw_write16(padapter, arg, extra_arg);
5909 RTW_INFO("rtw_write16(0x%x)=0x%04x\n", arg, rtw_read16(padapter, arg));
5910 break;
5911 case 4:
5912 rtw_write32(padapter, arg, extra_arg);
5913 RTW_INFO("rtw_write32(0x%x)=0x%08x\n", arg, rtw_read32(padapter, arg));
5914 break;
5915 }
5916 break;
5917 case 0x72: /* read_bb */
5918 RTW_INFO("read_bbreg(0x%x)=0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
5919 break;
5920 case 0x73: /* write_bb */
5921 rtw_hal_write_bbreg(padapter, arg, 0xffffffff, extra_arg);
5922 RTW_INFO("write_bbreg(0x%x)=0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
5923 break;
5924 case 0x74: /* read_rf */
5925 RTW_INFO("read RF_reg path(0x%02x),offset(0x%x),value(0x%08x)\n", minor_cmd, arg, rtw_hal_read_rfreg(padapter, minor_cmd, arg, 0xffffffff));
5926 break;
5927 case 0x75: /* write_rf */
5928 rtw_hal_write_rfreg(padapter, minor_cmd, arg, 0xffffffff, extra_arg);
5929 RTW_INFO("write RF_reg path(0x%02x),offset(0x%x),value(0x%08x)\n", minor_cmd, arg, rtw_hal_read_rfreg(padapter, minor_cmd, arg, 0xffffffff));
5930 break;
5931
5932 case 0x76:
5933 switch (minor_cmd) {
5934 case 0x00: /* normal mode, */
5935 padapter->recvpriv.is_signal_dbg = 0;
5936 break;
5937 case 0x01: /* dbg mode */
5938 padapter->recvpriv.is_signal_dbg = 1;
5939 extra_arg = extra_arg > 100 ? 100 : extra_arg;
5940 padapter->recvpriv.signal_strength_dbg = extra_arg;
5941 break;
5942 }
5943 break;
5944 case 0x78: /* IOL test */
5945 switch (minor_cmd) {
5946 #ifdef CONFIG_IOL
5947 case 0x04: { /* LLT table initialization test */
5948 u8 page_boundary = 0xf9;
5949 {
5950 struct xmit_frame *xmit_frame;
5951
5952 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
5953 if (xmit_frame == NULL) {
5954 ret = -ENOMEM;
5955 break;
5956 }
5957
5958 rtw_IOL_append_LLT_cmd(xmit_frame, page_boundary);
5959
5960
5961 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 500, 0))
5962 ret = -EPERM;
5963 }
5964 }
5965 break;
5966 case 0x05: { /* blink LED test */
5967 u16 reg = 0x4c;
5968 u32 blink_num = 50;
5969 u32 blink_delay_ms = 200;
5970 int i;
5971
5972 {
5973 struct xmit_frame *xmit_frame;
5974
5975 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
5976 if (xmit_frame == NULL) {
5977 ret = -ENOMEM;
5978 break;
5979 }
5980
5981 for (i = 0; i < blink_num; i++) {
5982 #ifdef CONFIG_IOL_NEW_GENERATION
5983 rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00, 0xff);
5984 rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
5985 rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08, 0xff);
5986 rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
5987 #else
5988 rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00);
5989 rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
5990 rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08);
5991 rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
5992 #endif
5993 }
5994 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, (blink_delay_ms * blink_num * 2) + 200, 0))
5995 ret = -EPERM;
5996 }
5997 }
5998 break;
5999
6000 case 0x06: { /* continuous wirte byte test */
6001 u16 reg = arg;
6002 u16 start_value = 0;
6003 u32 write_num = extra_arg;
6004 int i;
6005 u8 final;
6006
6007 {
6008 struct xmit_frame *xmit_frame;
6009
6010 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
6011 if (xmit_frame == NULL) {
6012 ret = -ENOMEM;
6013 break;
6014 }
6015
6016 for (i = 0; i < write_num; i++) {
6017 #ifdef CONFIG_IOL_NEW_GENERATION
6018 rtw_IOL_append_WB_cmd(xmit_frame, reg, i + start_value, 0xFF);
6019 #else
6020 rtw_IOL_append_WB_cmd(xmit_frame, reg, i + start_value);
6021 #endif
6022 }
6023 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
6024 ret = -EPERM;
6025 }
6026
6027 final = rtw_read8(padapter, reg);
6028 if (start_value + write_num - 1 == final)
6029 RTW_INFO("continuous IOL_CMD_WB_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
6030 else
6031 RTW_INFO("continuous IOL_CMD_WB_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
6032 }
6033 break;
6034
6035 case 0x07: { /* continuous wirte word test */
6036 u16 reg = arg;
6037 u16 start_value = 200;
6038 u32 write_num = extra_arg;
6039
6040 int i;
6041 u16 final;
6042
6043 {
6044 struct xmit_frame *xmit_frame;
6045
6046 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
6047 if (xmit_frame == NULL) {
6048 ret = -ENOMEM;
6049 break;
6050 }
6051
6052 for (i = 0; i < write_num; i++) {
6053 #ifdef CONFIG_IOL_NEW_GENERATION
6054 rtw_IOL_append_WW_cmd(xmit_frame, reg, i + start_value, 0xFFFF);
6055 #else
6056 rtw_IOL_append_WW_cmd(xmit_frame, reg, i + start_value);
6057 #endif
6058 }
6059 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
6060 ret = -EPERM;
6061 }
6062
6063 final = rtw_read16(padapter, reg);
6064 if (start_value + write_num - 1 == final)
6065 RTW_INFO("continuous IOL_CMD_WW_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
6066 else
6067 RTW_INFO("continuous IOL_CMD_WW_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
6068 }
6069 break;
6070
6071 case 0x08: { /* continuous wirte dword test */
6072 u16 reg = arg;
6073 u32 start_value = 0x110000c7;
6074 u32 write_num = extra_arg;
6075
6076 int i;
6077 u32 final;
6078
6079 {
6080 struct xmit_frame *xmit_frame;
6081
6082 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
6083 if (xmit_frame == NULL) {
6084 ret = -ENOMEM;
6085 break;
6086 }
6087
6088 for (i = 0; i < write_num; i++) {
6089 #ifdef CONFIG_IOL_NEW_GENERATION
6090 rtw_IOL_append_WD_cmd(xmit_frame, reg, i + start_value, 0xFFFFFFFF);
6091 #else
6092 rtw_IOL_append_WD_cmd(xmit_frame, reg, i + start_value);
6093 #endif
6094 }
6095 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
6096 ret = -EPERM;
6097
6098 }
6099
6100 final = rtw_read32(padapter, reg);
6101 if (start_value + write_num - 1 == final)
6102 RTW_INFO("continuous IOL_CMD_WD_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
6103 else
6104 RTW_INFO("continuous IOL_CMD_WD_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
6105 }
6106 break;
6107 #endif /* CONFIG_IOL */
6108 }
6109 break;
6110 case 0x79: {
6111 /*
6112 * dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15
6113 * dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15
6114 */
6115 u8 value = extra_arg & 0x0f;
6116 u8 sign = minor_cmd;
6117 u16 write_value = 0;
6118
6119 RTW_INFO("%s set RESP_TXAGC to %s %u\n", __func__, sign ? "minus" : "plus", value);
6120
6121 if (sign)
6122 value = value | 0x10;
6123
6124 write_value = value | (value << 5);
6125 rtw_write16(padapter, 0x6d9, write_value);
6126 }
6127 break;
6128 case 0x7a:
6129 receive_disconnect(padapter, pmlmeinfo->network.MacAddress
6130 , WLAN_REASON_EXPIRATION_CHK, _FALSE);
6131 break;
6132 case 0x7F:
6133 switch (minor_cmd) {
6134 case 0x0:
6135 RTW_INFO("fwstate=0x%x\n", get_fwstate(pmlmepriv));
6136 break;
6137 case 0x01:
6138 RTW_INFO("auth_alg=0x%x, enc_alg=0x%x, auth_type=0x%x, enc_type=0x%x\n",
6139 psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,
6140 psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus);
6141 break;
6142 case 0x03:
6143 RTW_INFO("qos_option=%d\n", pmlmepriv->qospriv.qos_option);
6144 #ifdef CONFIG_80211N_HT
6145 RTW_INFO("ht_option=%d\n", pmlmepriv->htpriv.ht_option);
6146 #endif /* CONFIG_80211N_HT */
6147 break;
6148 case 0x04:
6149 RTW_INFO("cur_ch=%d\n", pmlmeext->cur_channel);
6150 RTW_INFO("cur_bw=%d\n", pmlmeext->cur_bwmode);
6151 RTW_INFO("cur_ch_off=%d\n", pmlmeext->cur_ch_offset);
6152
6153 RTW_INFO("oper_ch=%d\n", rtw_get_oper_ch(padapter));
6154 RTW_INFO("oper_bw=%d\n", rtw_get_oper_bw(padapter));
6155 RTW_INFO("oper_ch_offet=%d\n", rtw_get_oper_choffset(padapter));
6156
6157 break;
6158 case 0x05:
6159 psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
6160 if (psta) {
6161 RTW_INFO("SSID=%s\n", cur_network->network.Ssid.Ssid);
6162 RTW_INFO("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->cmn.mac_addr));
6163 RTW_INFO("cur_channel=%d, cur_bwmode=%d, cur_ch_offset=%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
6164 RTW_INFO("rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
6165 RTW_INFO("state=0x%x, aid=%d, macid=%d, raid=%d\n",
6166 psta->state, psta->cmn.aid, psta->cmn.mac_id, psta->cmn.ra_info.rate_id);
6167 #ifdef CONFIG_80211N_HT
6168 RTW_INFO("qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
6169 RTW_INFO("bwmode=%d, ch_offset=%d, sgi_20m=%d,sgi_40m=%d\n"
6170 , psta->cmn.bw_mode, psta->htpriv.ch_offset, psta->htpriv.sgi_20m, psta->htpriv.sgi_40m);
6171 RTW_INFO("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
6172 RTW_INFO("agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
6173 #endif /* CONFIG_80211N_HT */
6174
6175 sta_rx_reorder_ctl_dump(RTW_DBGDUMP, psta);
6176 } else
6177 RTW_INFO("can't get sta's macaddr, cur_network's macaddr:" MAC_FMT "\n", MAC_ARG(cur_network->network.MacAddress));
6178 break;
6179 case 0x06: {
6180 u64 tsf = 0;
6181
6182 tsf = rtw_hal_get_tsftr_by_port(padapter, extra_arg);
6183 RTW_INFO(" PORT-%d TSF :%21lld\n", extra_arg, tsf);
6184 }
6185 break;
6186 case 0x07:
6187 RTW_INFO("bSurpriseRemoved=%s, bDriverStopped=%s\n"
6188 , rtw_is_surprise_removed(padapter) ? "True" : "False"
6189 , rtw_is_drv_stopped(padapter) ? "True" : "False");
6190 break;
6191 case 0x08: {
6192 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
6193 struct recv_priv *precvpriv = &padapter->recvpriv;
6194
6195 RTW_INFO("free_xmitbuf_cnt=%d, free_xmitframe_cnt=%d"
6196 ", free_xmit_extbuf_cnt=%d, free_xframe_ext_cnt=%d"
6197 ", free_recvframe_cnt=%d\n",
6198 pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt,
6199 pxmitpriv->free_xmit_extbuf_cnt, pxmitpriv->free_xframe_ext_cnt,
6200 precvpriv->free_recvframe_cnt);
6201 #ifdef CONFIG_USB_HCI
6202 RTW_INFO("rx_urb_pending_cn=%d\n", ATOMIC_READ(&(precvpriv->rx_pending_cnt)));
6203 #endif
6204 }
6205 break;
6206 case 0x09: {
6207 int i;
6208 _list *plist, *phead;
6209
6210 #ifdef CONFIG_AP_MODE
6211 RTW_INFO_DUMP("sta_dz_bitmap:", pstapriv->sta_dz_bitmap, pstapriv->aid_bmp_len);
6212 RTW_INFO_DUMP("tim_bitmap:", pstapriv->tim_bitmap, pstapriv->aid_bmp_len);
6213 #endif
6214 _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
6215
6216 for (i = 0; i < NUM_STA; i++) {
6217 phead = &(pstapriv->sta_hash[i]);
6218 plist = get_next(phead);
6219
6220 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
6221 psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
6222
6223 plist = get_next(plist);
6224
6225 if (extra_arg == psta->cmn.aid) {
6226 RTW_INFO("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->cmn.mac_addr));
6227 RTW_INFO("rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
6228 RTW_INFO("state=0x%x, aid=%d, macid=%d, raid=%d\n",
6229 psta->state, psta->cmn.aid, psta->cmn.mac_id, psta->cmn.ra_info.rate_id);
6230 #ifdef CONFIG_80211N_HT
6231 RTW_INFO("qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
6232 RTW_INFO("bwmode=%d, ch_offset=%d, sgi_20m=%d,sgi_40m=%d\n",
6233 psta->cmn.bw_mode, psta->htpriv.ch_offset, psta->htpriv.sgi_20m,
6234 psta->htpriv.sgi_40m);
6235 RTW_INFO("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
6236 RTW_INFO("agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
6237 #endif /* CONFIG_80211N_HT */
6238
6239 #ifdef CONFIG_AP_MODE
6240 RTW_INFO("capability=0x%x\n", psta->capability);
6241 RTW_INFO("flags=0x%x\n", psta->flags);
6242 RTW_INFO("wpa_psk=0x%x\n", psta->wpa_psk);
6243 RTW_INFO("wpa2_group_cipher=0x%x\n", psta->wpa2_group_cipher);
6244 RTW_INFO("wpa2_pairwise_cipher=0x%x\n", psta->wpa2_pairwise_cipher);
6245 RTW_INFO("qos_info=0x%x\n", psta->qos_info);
6246 #endif
6247 RTW_INFO("dot118021XPrivacy=0x%x\n", psta->dot118021XPrivacy);
6248
6249 sta_rx_reorder_ctl_dump(RTW_DBGDUMP, psta);
6250 }
6251
6252 }
6253 }
6254
6255 _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
6256
6257 }
6258 break;
6259
6260 case 0x0b: { /* Enable=1, Disable=0 driver control vrtl_carrier_sense. */
6261 /* u8 driver_vcs_en; */ /* Enable=1, Disable=0 driver control vrtl_carrier_sense. */
6262 /* u8 driver_vcs_type; */ /* force 0:disable VCS, 1:RTS-CTS, 2:CTS-to-self when vcs_en=1. */
6263
6264 if (arg == 0) {
6265 RTW_INFO("disable driver ctrl vcs\n");
6266 padapter->driver_vcs_en = 0;
6267 } else if (arg == 1) {
6268 RTW_INFO("enable driver ctrl vcs = %d\n", extra_arg);
6269 padapter->driver_vcs_en = 1;
6270
6271 if (extra_arg > 2)
6272 padapter->driver_vcs_type = 1;
6273 else
6274 padapter->driver_vcs_type = extra_arg;
6275 }
6276 }
6277 break;
6278 case 0x0c: { /* dump rx/tx packet */
6279 if (arg == 0) {
6280 RTW_INFO("dump rx packet (%d)\n", extra_arg);
6281 /* pHalData->bDumpRxPkt =extra_arg; */
6282 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_RXPKT, &(extra_arg));
6283 } else if (arg == 1) {
6284 RTW_INFO("dump tx packet (%d)\n", extra_arg);
6285 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(extra_arg));
6286 }
6287 }
6288 break;
6289 case 0x0e: {
6290 if (arg == 0) {
6291 RTW_INFO("disable driver ctrl rx_ampdu_factor\n");
6292 padapter->driver_rx_ampdu_factor = 0xFF;
6293 } else if (arg == 1) {
6294
6295 RTW_INFO("enable driver ctrl rx_ampdu_factor = %d\n", extra_arg);
6296
6297 if (extra_arg > 0x03)
6298 padapter->driver_rx_ampdu_factor = 0xFF;
6299 else
6300 padapter->driver_rx_ampdu_factor = extra_arg;
6301 }
6302 }
6303 break;
6304 #ifdef DBG_CONFIG_ERROR_DETECT
6305 case 0x0f: {
6306 if (extra_arg == 0) {
6307 RTW_INFO("###### silent reset test.......#####\n");
6308 rtw_hal_sreset_reset(padapter);
6309 } else {
6310 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
6311 struct sreset_priv *psrtpriv = &pHalData->srestpriv;
6312 psrtpriv->dbg_trigger_point = extra_arg;
6313 }
6314
6315 }
6316 break;
6317 case 0x15: {
6318 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
6319 RTW_INFO("==>silent resete cnts:%d\n", pwrpriv->ips_enter_cnts);
6320 }
6321 break;
6322
6323 #endif
6324
6325 case 0x10: /* driver version display */
6326 dump_drv_version(RTW_DBGDUMP);
6327 break;
6328 case 0x11: { /* dump linked status */
6329 int pre_mode;
6330 pre_mode = padapter->bLinkInfoDump;
6331 /* linked_info_dump(padapter,extra_arg); */
6332 if (extra_arg == 1 || (extra_arg == 0 && pre_mode == 1)) /* not consider pwr_saving 0: */
6333 padapter->bLinkInfoDump = extra_arg;
6334
6335 else if ((extra_arg == 2) || (extra_arg == 0 && pre_mode == 2)) { /* consider power_saving */
6336 /* RTW_INFO("linked_info_dump =%s\n", (padapter->bLinkInfoDump)?"enable":"disable") */
6337 linked_info_dump(padapter, extra_arg);
6338 }
6339
6340
6341
6342 }
6343 break;
6344 #ifdef CONFIG_80211N_HT
6345 case 0x12: { /* set rx_stbc */
6346 struct registry_priv *pregpriv = &padapter->registrypriv;
6347 /* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g */
6348 /* default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */
6349 if (pregpriv && (extra_arg == 0 || extra_arg == 1 || extra_arg == 2 || extra_arg == 3)) {
6350 pregpriv->rx_stbc = extra_arg;
6351 RTW_INFO("set rx_stbc=%d\n", pregpriv->rx_stbc);
6352 } else
6353 RTW_INFO("get rx_stbc=%d\n", pregpriv->rx_stbc);
6354
6355 }
6356 break;
6357 case 0x13: { /* set ampdu_enable */
6358 struct registry_priv *pregpriv = &padapter->registrypriv;
6359 /* 0: disable, 0x1:enable */
6360 if (pregpriv && extra_arg < 2) {
6361 pregpriv->ampdu_enable = extra_arg;
6362 RTW_INFO("set ampdu_enable=%d\n", pregpriv->ampdu_enable);
6363 } else
6364 RTW_INFO("get ampdu_enable=%d\n", pregpriv->ampdu_enable);
6365
6366 }
6367 break;
6368 #endif
6369 case 0x14: { /* get wifi_spec */
6370 struct registry_priv *pregpriv = &padapter->registrypriv;
6371 RTW_INFO("get wifi_spec=%d\n", pregpriv->wifi_spec);
6372
6373 }
6374 break;
6375
6376 #ifdef DBG_FIXED_CHAN
6377 case 0x17: {
6378 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
6379 printk("===> Fixed channel to %d\n", extra_arg);
6380 pmlmeext->fixed_chan = extra_arg;
6381
6382 }
6383 break;
6384 #endif
6385 #ifdef CONFIG_80211N_HT
6386 case 0x19: {
6387 struct registry_priv *pregistrypriv = &padapter->registrypriv;
6388 /* extra_arg : */
6389 /* BIT0: Enable VHT LDPC Rx, BIT1: Enable VHT LDPC Tx, */
6390 /* BIT4: Enable HT LDPC Rx, BIT5: Enable HT LDPC Tx */
6391 if (arg == 0) {
6392 RTW_INFO("driver disable LDPC\n");
6393 pregistrypriv->ldpc_cap = 0x00;
6394 } else if (arg == 1) {
6395 RTW_INFO("driver set LDPC cap = 0x%x\n", extra_arg);
6396 pregistrypriv->ldpc_cap = (u8)(extra_arg & 0x33);
6397 }
6398 }
6399 break;
6400 case 0x1a: {
6401 struct registry_priv *pregistrypriv = &padapter->registrypriv;
6402 /* extra_arg : */
6403 /* BIT0: Enable VHT STBC Rx, BIT1: Enable VHT STBC Tx, */
6404 /* BIT4: Enable HT STBC Rx, BIT5: Enable HT STBC Tx */
6405 if (arg == 0) {
6406 RTW_INFO("driver disable STBC\n");
6407 pregistrypriv->stbc_cap = 0x00;
6408 } else if (arg == 1) {
6409 RTW_INFO("driver set STBC cap = 0x%x\n", extra_arg);
6410 pregistrypriv->stbc_cap = (u8)(extra_arg & 0x33);
6411 }
6412 }
6413 break;
6414 #endif /* CONFIG_80211N_HT */
6415 case 0x1b: {
6416 struct registry_priv *pregistrypriv = &padapter->registrypriv;
6417
6418 if (arg == 0) {
6419 RTW_INFO("disable driver ctrl max_rx_rate, reset to default_rate_set\n");
6420 init_mlme_default_rate_set(padapter);
6421 #ifdef CONFIG_80211N_HT
6422 pregistrypriv->ht_enable = (u8)rtw_ht_enable;
6423 #endif /* CONFIG_80211N_HT */
6424 } else if (arg == 1) {
6425
6426 int i;
6427 u8 max_rx_rate;
6428
6429 RTW_INFO("enable driver ctrl max_rx_rate = 0x%x\n", extra_arg);
6430
6431 max_rx_rate = (u8)extra_arg;
6432
6433 if (max_rx_rate < 0xc) { /* max_rx_rate < MSC0->B or G -> disable HT */
6434 #ifdef CONFIG_80211N_HT
6435 pregistrypriv->ht_enable = 0;
6436 #endif /* CONFIG_80211N_HT */
6437 for (i = 0; i < NumRates; i++) {
6438 if (pmlmeext->datarate[i] > max_rx_rate)
6439 pmlmeext->datarate[i] = 0xff;
6440 }
6441
6442 }
6443 #ifdef CONFIG_80211N_HT
6444 else if (max_rx_rate < 0x1c) { /* mcs0~mcs15 */
6445 u32 mcs_bitmap = 0x0;
6446
6447 for (i = 0; i < ((max_rx_rate + 1) - 0xc); i++)
6448 mcs_bitmap |= BIT(i);
6449
6450 set_mcs_rate_by_mask(pmlmeext->default_supported_mcs_set, mcs_bitmap);
6451 }
6452 #endif /* CONFIG_80211N_HT */
6453 }
6454 }
6455 break;
6456 case 0x1c: { /* enable/disable driver control AMPDU Density for peer sta's rx */
6457 if (arg == 0) {
6458 RTW_INFO("disable driver ctrl ampdu density\n");
6459 padapter->driver_ampdu_spacing = 0xFF;
6460 } else if (arg == 1) {
6461
6462 RTW_INFO("enable driver ctrl ampdu density = %d\n", extra_arg);
6463
6464 if (extra_arg > 0x07)
6465 padapter->driver_ampdu_spacing = 0xFF;
6466 else
6467 padapter->driver_ampdu_spacing = extra_arg;
6468 }
6469 }
6470 break;
6471 #ifdef CONFIG_BACKGROUND_NOISE_MONITOR
6472 case 0x1e: {
6473 RTW_INFO("===========================================\n");
6474 rtw_noise_measure_curchan(padapter);
6475 RTW_INFO("===========================================\n");
6476 }
6477 break;
6478 #endif
6479
6480
6481 #if defined(CONFIG_SDIO_HCI) && defined(CONFIG_SDIO_INDIRECT_ACCESS) && defined(DBG_SDIO_INDIRECT_ACCESS)
6482 case 0x1f:
6483 {
6484 int i, j = 0, test_cnts = 0;
6485 static u8 test_code = 0x5A;
6486 static u32 data_misatch_cnt = 0, d_acc_err_cnt = 0;
6487
6488 u32 d_data, i_data;
6489 u32 imr;
6490
6491 test_cnts = extra_arg;
6492 for (i = 0; i < test_cnts; i++) {
6493 if (RTW_CANNOT_IO(padapter))
6494 break;
6495
6496 rtw_write8(padapter, 0x07, test_code);
6497
6498 d_data = rtw_read32(padapter, 0x04);
6499 imr = rtw_read32(padapter, 0x10250014);
6500 rtw_write32(padapter, 0x10250014, 0);
6501 rtw_msleep_os(50);
6502
6503 i_data = rtw_sd_iread32(padapter, 0x04);
6504
6505 rtw_write32(padapter, 0x10250014, imr);
6506
6507 if (d_data != i_data) {
6508 data_misatch_cnt++;
6509 RTW_ERR("d_data :0x%08x, i_data : 0x%08x\n", d_data, i_data);
6510 }
6511
6512 if (test_code != (i_data >> 24)) {
6513 d_acc_err_cnt++;
6514 rtw_write8(padapter, 0x07, 0xAA);
6515 RTW_ERR("test_code :0x%02x, i_data : 0x%08x\n", test_code, i_data);
6516 }
6517 if ((j++) == 100) {
6518 rtw_msleep_os(2000);
6519 RTW_INFO(" Indirect access testing..........%d/%d\n", i, test_cnts);
6520 j = 0;
6521 }
6522
6523 test_code = ~test_code;
6524 rtw_msleep_os(50);
6525 }
6526 RTW_INFO("========Indirect access test=========\n");
6527 RTW_INFO(" test_cnts = %d\n", test_cnts);
6528 RTW_INFO(" direct & indirect read32 data missatch cnts = %d\n", data_misatch_cnt);
6529 RTW_INFO(" indirect rdata is not equal to wdata cnts = %d\n", d_acc_err_cnt);
6530 RTW_INFO("========Indirect access test=========\n\n");
6531 data_misatch_cnt = d_acc_err_cnt = 0;
6532
6533 }
6534 break;
6535 #endif
6536 case 0x20:
6537 {
6538 if (arg == 0xAA) {
6539 u8 page_offset, page_num;
6540
6541 page_offset = (u8)(extra_arg >> 16);
6542 page_num = (u8)(extra_arg & 0xFF);
6543 rtw_dump_rsvd_page(RTW_DBGDUMP, padapter, page_offset, page_num);
6544 }
6545 #ifdef CONFIG_SUPPORT_FIFO_DUMP
6546 else {
6547 u8 fifo_sel;
6548 u32 addr, size;
6549
6550 fifo_sel = (u8)(arg & 0x0F);
6551 addr = (extra_arg >> 16) & 0xFFFF;
6552 size = extra_arg & 0xFFFF;
6553 rtw_dump_fifo(RTW_DBGDUMP, padapter, fifo_sel, addr, size);
6554 }
6555 #endif
6556 }
6557 break;
6558
6559 case 0x23: {
6560 RTW_INFO("turn %s the bNotifyChannelChange Variable\n", (extra_arg == 1) ? "on" : "off");
6561 padapter->bNotifyChannelChange = extra_arg;
6562 break;
6563 }
6564 case 0x24: {
6565 #ifdef CONFIG_P2P
6566 RTW_INFO("turn %s the bShowGetP2PState Variable\n", (extra_arg == 1) ? "on" : "off");
6567 padapter->bShowGetP2PState = extra_arg;
6568 #endif /* CONFIG_P2P */
6569 break;
6570 }
6571 #ifdef CONFIG_GPIO_API
6572 case 0x25: { /* Get GPIO register */
6573 /*
6574 * dbg 0x7f250000 [gpio_num], Get gpio value, gpio_num:0~7
6575 */
6576
6577 u8 value;
6578 RTW_INFO("Read GPIO Value extra_arg = %d\n", extra_arg);
6579 value = rtw_hal_get_gpio(padapter, extra_arg);
6580 RTW_INFO("Read GPIO Value = %d\n", value);
6581 break;
6582 }
6583 case 0x26: { /* Set GPIO direction */
6584
6585 /* dbg 0x7f26000x [y], Set gpio direction,
6586 * x: gpio_num,4~7 y: indicate direction, 0~1
6587 */
6588
6589 int value;
6590 RTW_INFO("Set GPIO Direction! arg = %d ,extra_arg=%d\n", arg , extra_arg);
6591 value = rtw_hal_config_gpio(padapter, arg, extra_arg);
6592 RTW_INFO("Set GPIO Direction %s\n", (value == -1) ? "Fail!!!" : "Success");
6593 break;
6594 }
6595 case 0x27: { /* Set GPIO output direction value */
6596 /*
6597 * dbg 0x7f27000x [y], Set gpio output direction value,
6598 * x: gpio_num,4~7 y: indicate direction, 0~1
6599 */
6600
6601 int value;
6602 RTW_INFO("Set GPIO Value! arg = %d ,extra_arg=%d\n", arg , extra_arg);
6603 value = rtw_hal_set_gpio_output_value(padapter, arg, extra_arg);
6604 RTW_INFO("Set GPIO Value %s\n", (value == -1) ? "Fail!!!" : "Success");
6605 break;
6606 }
6607 #endif
6608 #ifdef DBG_CMD_QUEUE
6609 case 0x28: {
6610 dump_cmd_id = extra_arg;
6611 RTW_INFO("dump_cmd_id:%d\n", dump_cmd_id);
6612 }
6613 break;
6614 #endif /* DBG_CMD_QUEUE */
6615 case 0xaa: {
6616 if ((extra_arg & 0x7F) > 0x3F)
6617 extra_arg = 0xFF;
6618 RTW_INFO("chang data rate to :0x%02x\n", extra_arg);
6619 padapter->fix_rate = extra_arg;
6620 }
6621 break;
6622 case 0xdd: { /* registers dump , 0 for mac reg,1 for bb reg, 2 for rf reg */
6623 if (extra_arg == 0)
6624 mac_reg_dump(RTW_DBGDUMP, padapter);
6625 else if (extra_arg == 1)
6626 bb_reg_dump(RTW_DBGDUMP, padapter);
6627 else if (extra_arg == 2)
6628 rf_reg_dump(RTW_DBGDUMP, padapter);
6629 else if (extra_arg == 11)
6630 bb_reg_dump_ex(RTW_DBGDUMP, padapter);
6631 }
6632 break;
6633
6634 case 0xee: {
6635 RTW_INFO(" === please control /proc to trun on/off PHYDM func ===\n");
6636 }
6637 break;
6638
6639 case 0xfd:
6640 rtw_write8(padapter, 0xc50, arg);
6641 RTW_INFO("wr(0xc50)=0x%x\n", rtw_read8(padapter, 0xc50));
6642 rtw_write8(padapter, 0xc58, arg);
6643 RTW_INFO("wr(0xc58)=0x%x\n", rtw_read8(padapter, 0xc58));
6644 break;
6645 case 0xfe:
6646 RTW_INFO("rd(0xc50)=0x%x\n", rtw_read8(padapter, 0xc50));
6647 RTW_INFO("rd(0xc58)=0x%x\n", rtw_read8(padapter, 0xc58));
6648 break;
6649 case 0xff: {
6650 RTW_INFO("dbg(0x210)=0x%x\n", rtw_read32(padapter, 0x210));
6651 RTW_INFO("dbg(0x608)=0x%x\n", rtw_read32(padapter, 0x608));
6652 RTW_INFO("dbg(0x280)=0x%x\n", rtw_read32(padapter, 0x280));
6653 RTW_INFO("dbg(0x284)=0x%x\n", rtw_read32(padapter, 0x284));
6654 RTW_INFO("dbg(0x288)=0x%x\n", rtw_read32(padapter, 0x288));
6655
6656 RTW_INFO("dbg(0x664)=0x%x\n", rtw_read32(padapter, 0x664));
6657
6658
6659 RTW_INFO("\n");
6660
6661 RTW_INFO("dbg(0x430)=0x%x\n", rtw_read32(padapter, 0x430));
6662 RTW_INFO("dbg(0x438)=0x%x\n", rtw_read32(padapter, 0x438));
6663
6664 RTW_INFO("dbg(0x440)=0x%x\n", rtw_read32(padapter, 0x440));
6665
6666 RTW_INFO("dbg(0x458)=0x%x\n", rtw_read32(padapter, 0x458));
6667
6668 RTW_INFO("dbg(0x484)=0x%x\n", rtw_read32(padapter, 0x484));
6669 RTW_INFO("dbg(0x488)=0x%x\n", rtw_read32(padapter, 0x488));
6670
6671 RTW_INFO("dbg(0x444)=0x%x\n", rtw_read32(padapter, 0x444));
6672 RTW_INFO("dbg(0x448)=0x%x\n", rtw_read32(padapter, 0x448));
6673 RTW_INFO("dbg(0x44c)=0x%x\n", rtw_read32(padapter, 0x44c));
6674 RTW_INFO("dbg(0x450)=0x%x\n", rtw_read32(padapter, 0x450));
6675 }
6676 break;
6677 }
6678 break;
6679 default:
6680 RTW_INFO("error dbg cmd!\n");
6681 break;
6682 }
6683
6684 #endif
6685 return ret;
6686
6687 }
6688
6689 #ifdef CONFIG_IOCTL_WEXT
6690 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
6691 {
6692 uint ret = 0;
6693 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
6694
6695 switch (name) {
6696 case IEEE_PARAM_WPA_ENABLED:
6697
6698 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
6699
6700 /* ret = ieee80211_wpa_enable(ieee, value); */
6701
6702 switch ((value) & 0xff) {
6703 case 1: /* WPA */
6704 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
6705 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
6706 break;
6707 case 2: /* WPA2 */
6708 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
6709 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
6710 break;
6711 }
6712
6713
6714 break;
6715
6716 case IEEE_PARAM_TKIP_COUNTERMEASURES:
6717 /* ieee->tkip_countermeasures=value; */
6718 break;
6719
6720 case IEEE_PARAM_DROP_UNENCRYPTED: {
6721 /* HACK:
6722 *
6723 * wpa_supplicant calls set_wpa_enabled when the driver
6724 * is loaded and unloaded, regardless of if WPA is being
6725 * used. No other calls are made which can be used to
6726 * determine if encryption will be used or not prior to
6727 * association being expected. If encryption is not being
6728 * used, drop_unencrypted is set to false, else true -- we
6729 * can use this to determine if the CAP_PRIVACY_ON bit should
6730 * be set.
6731 */
6732
6733 #if 0
6734 struct ieee80211_security sec = {
6735 .flags = SEC_ENABLED,
6736 .enabled = value,
6737 };
6738 ieee->drop_unencrypted = value;
6739 /* We only change SEC_LEVEL for open mode. Others
6740 * are set by ipw_wpa_set_encryption.
6741 */
6742 if (!value) {
6743 sec.flags |= SEC_LEVEL;
6744 sec.level = SEC_LEVEL_0;
6745 } else {
6746 sec.flags |= SEC_LEVEL;
6747 sec.level = SEC_LEVEL_1;
6748 }
6749 if (ieee->set_security)
6750 ieee->set_security(ieee->dev, &sec);
6751 #endif
6752 break;
6753
6754 }
6755 case IEEE_PARAM_PRIVACY_INVOKED:
6756
6757 /* ieee->privacy_invoked=value; */
6758
6759 break;
6760
6761 case IEEE_PARAM_AUTH_ALGS:
6762
6763 ret = wpa_set_auth_algs(dev, value);
6764
6765 break;
6766
6767 case IEEE_PARAM_IEEE_802_1X:
6768
6769 /* ieee->ieee802_1x=value; */
6770
6771 break;
6772
6773 case IEEE_PARAM_WPAX_SELECT:
6774
6775 /* added for WPA2 mixed mode */
6776 /*RTW_WARN("------------------------>wpax value = %x\n", value);*/
6777 /*
6778 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
6779 ieee->wpax_type_set = 1;
6780 ieee->wpax_type_notify = value;
6781 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
6782 */
6783
6784 break;
6785
6786 default:
6787
6788
6789
6790 ret = -EOPNOTSUPP;
6791
6792
6793 break;
6794
6795 }
6796
6797 return ret;
6798
6799 }
6800
6801 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
6802 {
6803 int ret = 0;
6804 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
6805
6806 switch (command) {
6807 case IEEE_MLME_STA_DEAUTH:
6808
6809 if (!rtw_set_802_11_disassociate(padapter))
6810 ret = -1;
6811
6812 break;
6813
6814 case IEEE_MLME_STA_DISASSOC:
6815
6816 if (!rtw_set_802_11_disassociate(padapter))
6817 ret = -1;
6818
6819 break;
6820
6821 default:
6822 ret = -EOPNOTSUPP;
6823 break;
6824 }
6825 #ifdef CONFIG_RTW_REPEATER_SON
6826 rtw_rson_do_disconnect(padapter);
6827 #endif
6828 return ret;
6829
6830 }
6831
6832 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
6833 {
6834 struct ieee_param *param;
6835 uint ret = 0;
6836
6837 /* down(&ieee->wx_sem); */
6838
6839 if (p->length < sizeof(struct ieee_param) || !p->pointer) {
6840 ret = -EINVAL;
6841 goto out;
6842 }
6843
6844 param = (struct ieee_param *)rtw_malloc(p->length);
6845 if (param == NULL) {
6846 ret = -ENOMEM;
6847 goto out;
6848 }
6849
6850 if (copy_from_user(param, p->pointer, p->length)) {
6851 rtw_mfree((u8 *)param, p->length);
6852 ret = -EFAULT;
6853 goto out;
6854 }
6855
6856 switch (param->cmd) {
6857
6858 case IEEE_CMD_SET_WPA_PARAM:
6859 ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
6860 break;
6861
6862 case IEEE_CMD_SET_WPA_IE:
6863 /* ret = wpa_set_wpa_ie(dev, param, p->length); */
6864 ret = rtw_set_wpa_ie((_adapter *)rtw_netdev_priv(dev), (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
6865 break;
6866
6867 case IEEE_CMD_SET_ENCRYPTION:
6868 ret = wpa_set_encryption(dev, param, p->length);
6869 break;
6870
6871 case IEEE_CMD_MLME:
6872 ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
6873 break;
6874
6875 default:
6876 RTW_INFO("Unknown WPA supplicant request: %d\n", param->cmd);
6877 ret = -EOPNOTSUPP;
6878 break;
6879
6880 }
6881
6882 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
6883 ret = -EFAULT;
6884
6885 rtw_mfree((u8 *)param, p->length);
6886
6887 out:
6888
6889 /* up(&ieee->wx_sem); */
6890
6891 return ret;
6892
6893 }
6894
6895 #ifdef CONFIG_AP_MODE
6896 static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
6897 {
6898 int ret = 0;
6899 u32 wep_key_idx, wep_key_len, wep_total_len;
6900 NDIS_802_11_WEP *pwep = NULL;
6901 struct sta_info *psta = NULL, *pbcmc_sta = NULL;
6902 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
6903 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
6904 struct security_priv *psecuritypriv = &(padapter->securitypriv);
6905 struct sta_priv *pstapriv = &padapter->stapriv;
6906
6907 RTW_INFO("%s\n", __FUNCTION__);
6908
6909 param->u.crypt.err = 0;
6910 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
6911
6912 /* sizeof(struct ieee_param) = 64 bytes; */
6913 /* if (param_len != (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) */
6914 if (param_len != sizeof(struct ieee_param) + param->u.crypt.key_len) {
6915 ret = -EINVAL;
6916 goto exit;
6917 }
6918
6919 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
6920 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
6921 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
6922 if (param->u.crypt.idx >= WEP_KEYS
6923 #ifdef CONFIG_IEEE80211W
6924 && param->u.crypt.idx > BIP_MAX_KEYID
6925 #endif /* CONFIG_IEEE80211W */
6926 ) {
6927 ret = -EINVAL;
6928 goto exit;
6929 }
6930 } else {
6931 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
6932 if (!psta) {
6933 /* ret = -EINVAL; */
6934 RTW_INFO("rtw_set_encryption(), sta has already been removed or never been added\n");
6935 goto exit;
6936 }
6937 }
6938
6939 if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
6940 /* todo:clear default encryption keys */
6941
6942 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
6943 psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
6944 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
6945 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
6946
6947 RTW_INFO("clear default encryption keys, keyid=%d\n", param->u.crypt.idx);
6948
6949 goto exit;
6950 }
6951
6952
6953 if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
6954 RTW_INFO("r871x_set_encryption, crypt.alg = WEP\n");
6955
6956 wep_key_idx = param->u.crypt.idx;
6957 wep_key_len = param->u.crypt.key_len;
6958
6959 RTW_INFO("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
6960
6961 if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
6962 ret = -EINVAL;
6963 goto exit;
6964 }
6965
6966
6967 if (wep_key_len > 0) {
6968 wep_key_len = wep_key_len <= 5 ? 5 : 13;
6969 wep_total_len = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
6970 pwep = (NDIS_802_11_WEP *)rtw_malloc(wep_total_len);
6971 if (pwep == NULL) {
6972 RTW_INFO(" r871x_set_encryption: pwep allocate fail !!!\n");
6973 goto exit;
6974 }
6975
6976 _rtw_memset(pwep, 0, wep_total_len);
6977
6978 pwep->KeyLength = wep_key_len;
6979 pwep->Length = wep_total_len;
6980
6981 }
6982
6983 pwep->KeyIndex = wep_key_idx;
6984
6985 _rtw_memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
6986
6987 if (param->u.crypt.set_tx) {
6988 RTW_INFO("wep, set_tx=1\n");
6989
6990 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
6991 psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
6992 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
6993 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
6994
6995 if (pwep->KeyLength == 13) {
6996 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
6997 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
6998 }
6999
7000
7001 psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
7002
7003 _rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
7004
7005 psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
7006
7007 rtw_ap_set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx, 1);
7008 } else {
7009 RTW_INFO("wep, set_tx=0\n");
7010
7011 /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
7012 /* "psecuritypriv->dot11PrivacyKeyIndex=keyid", but can rtw_set_key to cam */
7013
7014 _rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
7015
7016 psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
7017
7018 rtw_ap_set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx, 0);
7019 }
7020
7021 goto exit;
7022
7023 }
7024
7025
7026 if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) /* */ { /* group key */
7027 if (param->u.crypt.set_tx == 1) {
7028 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
7029 RTW_INFO(FUNC_ADPT_FMT" set WEP TX GTK idx:%u, len:%u\n"
7030 , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
7031 _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
7032 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
7033 if (param->u.crypt.key_len == 13)
7034 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
7035
7036 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
7037 RTW_INFO(FUNC_ADPT_FMT" set TKIP TX GTK idx:%u, len:%u\n"
7038 , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
7039 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
7040 _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
7041 /* set mic key */
7042 _rtw_memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
7043 _rtw_memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
7044 psecuritypriv->busetkipkey = _TRUE;
7045
7046 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
7047 RTW_INFO(FUNC_ADPT_FMT" set CCMP TX GTK idx:%u, len:%u\n"
7048 , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
7049 psecuritypriv->dot118021XGrpPrivacy = _AES_;
7050 _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
7051
7052 #ifdef CONFIG_IEEE80211W
7053 } else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
7054 RTW_INFO(FUNC_ADPT_FMT" set TX IGTK idx:%u, len:%u\n"
7055 , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
7056 _rtw_memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
7057 psecuritypriv->dot11wBIPKeyid = param->u.crypt.idx;
7058 psecuritypriv->dot11wBIPtxpn.val = RTW_GET_LE64(param->u.crypt.seq);
7059 psecuritypriv->binstallBIPkey = _TRUE;
7060 goto exit;
7061 #endif /* CONFIG_IEEE80211W */
7062
7063 } else if (strcmp(param->u.crypt.alg, "none") == 0) {
7064 RTW_INFO(FUNC_ADPT_FMT" clear group key, idx:%u\n"
7065 , FUNC_ADPT_ARG(padapter), param->u.crypt.idx);
7066 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
7067 } else {
7068 RTW_WARN(FUNC_ADPT_FMT" set group key, not support\n"
7069 , FUNC_ADPT_ARG(padapter));
7070 goto exit;
7071 }
7072
7073 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
7074 pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
7075 if (pbcmc_sta) {
7076 pbcmc_sta->dot11txpn.val = RTW_GET_LE64(param->u.crypt.seq);
7077 pbcmc_sta->ieee8021x_blocked = _FALSE;
7078 pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; /* rx will use bmc_sta's dot118021XPrivacy */
7079 }
7080 psecuritypriv->binstallGrpkey = _TRUE;
7081 psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* !!! */
7082
7083 rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
7084 }
7085
7086 goto exit;
7087
7088 }
7089
7090 if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x */
7091 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
7092 if (param->u.crypt.set_tx == 1) {
7093 _rtw_memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
7094
7095 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
7096 RTW_INFO(FUNC_ADPT_FMT" set WEP PTK of "MAC_FMT" idx:%u, len:%u\n"
7097 , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
7098 , param->u.crypt.idx, param->u.crypt.key_len);
7099 psta->dot118021XPrivacy = _WEP40_;
7100 if (param->u.crypt.key_len == 13)
7101 psta->dot118021XPrivacy = _WEP104_;
7102
7103 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
7104 RTW_INFO(FUNC_ADPT_FMT" set TKIP PTK of "MAC_FMT" idx:%u, len:%u\n"
7105 , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
7106 , param->u.crypt.idx, param->u.crypt.key_len);
7107 psta->dot118021XPrivacy = _TKIP_;
7108 /* set mic key */
7109 _rtw_memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
7110 _rtw_memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
7111 psecuritypriv->busetkipkey = _TRUE;
7112
7113 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
7114 RTW_INFO(FUNC_ADPT_FMT" set CCMP PTK of "MAC_FMT" idx:%u, len:%u\n"
7115 , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
7116 , param->u.crypt.idx, param->u.crypt.key_len);
7117 psta->dot118021XPrivacy = _AES_;
7118
7119 } else if (strcmp(param->u.crypt.alg, "none") == 0) {
7120 RTW_INFO(FUNC_ADPT_FMT" clear pairwise key of "MAC_FMT" idx:%u\n"
7121 , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
7122 , param->u.crypt.idx);
7123 psta->dot118021XPrivacy = _NO_PRIVACY_;
7124
7125 } else {
7126 RTW_WARN(FUNC_ADPT_FMT" set pairwise key of "MAC_FMT", not support\n"
7127 , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr));
7128 goto exit;
7129 }
7130
7131 psta->dot11txpn.val = RTW_GET_LE64(param->u.crypt.seq);
7132 psta->dot11rxpn.val = RTW_GET_LE64(param->u.crypt.seq);
7133 psta->ieee8021x_blocked = _FALSE;
7134
7135 if (psta->dot118021XPrivacy != _NO_PRIVACY_) {
7136 psta->bpairwise_key_installed = _TRUE;
7137
7138 /* WPA2 key-handshake has completed */
7139 if (psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK)
7140 psta->state &= (~WIFI_UNDER_KEY_HANDSHAKE);
7141 }
7142
7143 rtw_ap_set_pairwise_key(padapter, psta);
7144 } else {
7145 RTW_WARN(FUNC_ADPT_FMT" set group key of "MAC_FMT", not support\n"
7146 , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr));
7147 goto exit;
7148 }
7149
7150 }
7151
7152 }
7153
7154 exit:
7155
7156 if (pwep)
7157 rtw_mfree((u8 *)pwep, wep_total_len);
7158
7159 return ret;
7160
7161 }
7162
7163 static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
7164 {
7165 int ret = 0;
7166 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7167 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7168 struct sta_priv *pstapriv = &padapter->stapriv;
7169 unsigned char *pbuf = param->u.bcn_ie.buf;
7170
7171
7172 RTW_INFO("%s, len=%d\n", __FUNCTION__, len);
7173
7174 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
7175 return -EINVAL;
7176
7177 _rtw_memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
7178
7179 if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
7180 pstapriv->max_num_sta = NUM_STA;
7181
7182
7183 if (rtw_check_beacon_data(padapter, pbuf, (len - 12 - 2)) == _SUCCESS) /* 12 = param header, 2:no packed */
7184 ret = 0;
7185 else
7186 ret = -EINVAL;
7187
7188
7189 return ret;
7190
7191 }
7192
7193 static int rtw_hostapd_sta_flush(struct net_device *dev)
7194 {
7195 /* _irqL irqL; */
7196 /* _list *phead, *plist; */
7197 int ret = 0;
7198 /* struct sta_info *psta = NULL; */
7199 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7200 /* struct sta_priv *pstapriv = &padapter->stapriv; */
7201
7202 RTW_INFO("%s\n", __FUNCTION__);
7203
7204 flush_all_cam_entry(padapter); /* clear CAM */
7205 #ifdef CONFIG_AP_MODE
7206 ret = rtw_sta_flush(padapter, _TRUE);
7207 #endif
7208 return ret;
7209
7210 }
7211
7212 static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
7213 {
7214 int ret = 0;
7215 struct sta_info *psta = NULL;
7216 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7217 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7218 struct sta_priv *pstapriv = &padapter->stapriv;
7219
7220 RTW_INFO("rtw_add_sta(aid=%d)=" MAC_FMT "\n", param->u.add_sta.aid, MAC_ARG(param->sta_addr));
7221
7222 if (check_fwstate(pmlmepriv, (WIFI_ASOC_STATE | WIFI_AP_STATE)) != _TRUE)
7223 return -EINVAL;
7224
7225 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
7226 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
7227 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
7228 return -EINVAL;
7229
7230 #if 0
7231 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
7232 if (psta) {
7233 RTW_INFO("rtw_add_sta(), free has been added psta=%p\n", psta);
7234 /* _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */
7235 rtw_free_stainfo(padapter, psta);
7236 /* _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */
7237
7238 psta = NULL;
7239 }
7240 #endif
7241 /* psta = rtw_alloc_stainfo(pstapriv, param->sta_addr); */
7242 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
7243 if (psta) {
7244 int flags = param->u.add_sta.flags;
7245
7246 /* RTW_INFO("rtw_add_sta(), init sta's variables, psta=%p\n", psta); */
7247
7248 psta->cmn.aid = param->u.add_sta.aid;/* aid=1~2007 */
7249
7250 _rtw_memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
7251
7252
7253 /* check wmm cap. */
7254 if (WLAN_STA_WME & flags)
7255 psta->qos_option = 1;
7256 else
7257 psta->qos_option = 0;
7258
7259 if (pmlmepriv->qospriv.qos_option == 0)
7260 psta->qos_option = 0;
7261
7262
7263 #ifdef CONFIG_80211N_HT
7264 /* chec 802.11n ht cap. */
7265 if (padapter->registrypriv.ht_enable &&
7266 is_supported_ht(padapter->registrypriv.wireless_mode) &&
7267 (WLAN_STA_HT & flags)) {
7268 psta->htpriv.ht_option = _TRUE;
7269 psta->qos_option = 1;
7270 _rtw_memcpy((void *)&psta->htpriv.ht_cap, (void *)¶m->u.add_sta.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
7271 } else
7272 psta->htpriv.ht_option = _FALSE;
7273
7274 if (pmlmepriv->htpriv.ht_option == _FALSE)
7275 psta->htpriv.ht_option = _FALSE;
7276
7277 #endif
7278
7279
7280 update_sta_info_apmode(padapter, psta);
7281
7282
7283 } else
7284 ret = -ENOMEM;
7285
7286 return ret;
7287
7288 }
7289
7290 static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
7291 {
7292 _irqL irqL;
7293 int ret = 0;
7294 struct sta_info *psta = NULL;
7295 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7296 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7297 struct sta_priv *pstapriv = &padapter->stapriv;
7298
7299 RTW_INFO("rtw_del_sta=" MAC_FMT "\n", MAC_ARG(param->sta_addr));
7300
7301 if (check_fwstate(pmlmepriv, (WIFI_ASOC_STATE | WIFI_AP_STATE)) != _TRUE)
7302 return -EINVAL;
7303
7304 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
7305 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
7306 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
7307 return -EINVAL;
7308
7309 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
7310 if (psta) {
7311 u8 updated = _FALSE;
7312
7313 /* RTW_INFO("free psta=%p, aid=%d\n", psta, psta->cmn.aid); */
7314
7315 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
7316 if (rtw_is_list_empty(&psta->asoc_list) == _FALSE) {
7317 rtw_list_delete(&psta->asoc_list);
7318 pstapriv->asoc_list_cnt--;
7319 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
7320 if (psta->tbtx_enable)
7321 pstapriv->tbtx_asoc_list_cnt--;
7322 #endif
7323 updated = ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING, _TRUE);
7324
7325 }
7326 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
7327
7328 associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);
7329
7330 psta = NULL;
7331
7332 } else {
7333 RTW_INFO("rtw_del_sta(), sta has already been removed or never been added\n");
7334
7335 /* ret = -1; */
7336 }
7337
7338
7339 return ret;
7340
7341 }
7342
7343 static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
7344 {
7345 int ret = 0;
7346 struct sta_info *psta = NULL;
7347 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7348 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7349 struct sta_priv *pstapriv = &padapter->stapriv;
7350 struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
7351 struct sta_data *psta_data = (struct sta_data *)param_ex->data;
7352
7353 RTW_INFO("rtw_ioctl_get_sta_info, sta_addr: " MAC_FMT "\n", MAC_ARG(param_ex->sta_addr));
7354
7355 if (check_fwstate(pmlmepriv, (WIFI_ASOC_STATE | WIFI_AP_STATE)) != _TRUE)
7356 return -EINVAL;
7357
7358 if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
7359 param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
7360 param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff)
7361 return -EINVAL;
7362
7363 psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
7364 if (psta) {
7365 #if 0
7366 struct {
7367 u16 aid;
7368 u16 capability;
7369 int flags;
7370 u32 sta_set;
7371 u8 tx_supp_rates[16];
7372 u32 tx_supp_rates_len;
7373 struct rtw_ieee80211_ht_cap ht_cap;
7374 u64 rx_pkts;
7375 u64 rx_bytes;
7376 u64 rx_drops;
7377 u64 tx_pkts;
7378 u64 tx_bytes;
7379 u64 tx_drops;
7380 } get_sta;
7381 #endif
7382 psta_data->aid = (u16)psta->cmn.aid;
7383 psta_data->capability = psta->capability;
7384 psta_data->flags = psta->flags;
7385
7386 /*
7387 nonerp_set : BIT(0)
7388 no_short_slot_time_set : BIT(1)
7389 no_short_preamble_set : BIT(2)
7390 no_ht_gf_set : BIT(3)
7391 no_ht_set : BIT(4)
7392 ht_20mhz_set : BIT(5)
7393 */
7394
7395 psta_data->sta_set = ((psta->nonerp_set) |
7396 (psta->no_short_slot_time_set << 1) |
7397 (psta->no_short_preamble_set << 2) |
7398 (psta->no_ht_gf_set << 3) |
7399 (psta->no_ht_set << 4) |
7400 (psta->ht_20mhz_set << 5));
7401
7402 psta_data->tx_supp_rates_len = psta->bssratelen;
7403 _rtw_memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
7404 #ifdef CONFIG_80211N_HT
7405 if(padapter->registrypriv.ht_enable && is_supported_ht(padapter->registrypriv.wireless_mode))
7406 _rtw_memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
7407 #endif /* CONFIG_80211N_HT */
7408 psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
7409 psta_data->rx_bytes = psta->sta_stats.rx_bytes;
7410 psta_data->rx_drops = psta->sta_stats.rx_drops;
7411
7412 psta_data->tx_pkts = psta->sta_stats.tx_pkts;
7413 psta_data->tx_bytes = psta->sta_stats.tx_bytes;
7414 psta_data->tx_drops = psta->sta_stats.tx_drops;
7415
7416
7417 } else
7418 ret = -1;
7419
7420 return ret;
7421
7422 }
7423
7424 static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
7425 {
7426 int ret = 0;
7427 struct sta_info *psta = NULL;
7428 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7429 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7430 struct sta_priv *pstapriv = &padapter->stapriv;
7431
7432 RTW_INFO("rtw_get_sta_wpaie, sta_addr: " MAC_FMT "\n", MAC_ARG(param->sta_addr));
7433
7434 if (check_fwstate(pmlmepriv, (WIFI_ASOC_STATE | WIFI_AP_STATE)) != _TRUE)
7435 return -EINVAL;
7436
7437 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
7438 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
7439 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
7440 return -EINVAL;
7441
7442 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
7443 if (psta) {
7444 if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_GENERIC)) {
7445 int wpa_ie_len;
7446 int copy_len;
7447
7448 wpa_ie_len = psta->wpa_ie[1];
7449
7450 copy_len = ((wpa_ie_len + 2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)) : (wpa_ie_len + 2);
7451
7452 param->u.wpa_ie.len = copy_len;
7453
7454 _rtw_memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
7455 } else {
7456 /* ret = -1; */
7457 RTW_INFO("sta's wpa_ie is NONE\n");
7458 }
7459 } else
7460 ret = -1;
7461
7462 return ret;
7463
7464 }
7465
7466 static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
7467 {
7468 int ret = 0;
7469 unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
7470 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7471 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7472 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
7473 int ie_len;
7474
7475 RTW_INFO("%s, len=%d\n", __FUNCTION__, len);
7476
7477 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
7478 return -EINVAL;
7479
7480 ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
7481
7482
7483 if (pmlmepriv->wps_beacon_ie) {
7484 rtw_mfree(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len);
7485 pmlmepriv->wps_beacon_ie = NULL;
7486 }
7487
7488 if (ie_len > 0) {
7489 pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
7490 pmlmepriv->wps_beacon_ie_len = ie_len;
7491 if (pmlmepriv->wps_beacon_ie == NULL) {
7492 RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
7493 return -EINVAL;
7494 }
7495
7496 _rtw_memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
7497
7498 update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, _TRUE, 0);
7499
7500 pmlmeext->bstart_bss = _TRUE;
7501
7502 }
7503
7504
7505 return ret;
7506
7507 }
7508
7509 static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
7510 {
7511 int ret = 0;
7512 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7513 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7514 int ie_len;
7515
7516 RTW_INFO("%s, len=%d\n", __FUNCTION__, len);
7517
7518 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
7519 return -EINVAL;
7520
7521 ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
7522
7523
7524 if (pmlmepriv->wps_probe_resp_ie) {
7525 rtw_mfree(pmlmepriv->wps_probe_resp_ie, pmlmepriv->wps_probe_resp_ie_len);
7526 pmlmepriv->wps_probe_resp_ie = NULL;
7527 }
7528
7529 if (ie_len > 0) {
7530 pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
7531 pmlmepriv->wps_probe_resp_ie_len = ie_len;
7532 if (pmlmepriv->wps_probe_resp_ie == NULL) {
7533 RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
7534 return -EINVAL;
7535 }
7536 _rtw_memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
7537 }
7538
7539
7540 return ret;
7541
7542 }
7543
7544 static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
7545 {
7546 int ret = 0;
7547 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7548 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7549 int ie_len;
7550
7551 RTW_INFO("%s, len=%d\n", __FUNCTION__, len);
7552
7553 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
7554 return -EINVAL;
7555
7556 ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
7557
7558
7559 if (pmlmepriv->wps_assoc_resp_ie) {
7560 rtw_mfree(pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
7561 pmlmepriv->wps_assoc_resp_ie = NULL;
7562 }
7563
7564 if (ie_len > 0) {
7565 pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
7566 pmlmepriv->wps_assoc_resp_ie_len = ie_len;
7567 if (pmlmepriv->wps_assoc_resp_ie == NULL) {
7568 RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
7569 return -EINVAL;
7570 }
7571
7572 _rtw_memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
7573 }
7574
7575
7576 return ret;
7577
7578 }
7579
7580 static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
7581 {
7582 int ret = 0;
7583 _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
7584 struct mlme_priv *mlmepriv = &(adapter->mlmepriv);
7585 struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
7586 struct mlme_ext_info *mlmeinfo = &(mlmeext->mlmext_info);
7587 int ie_len;
7588 u8 *ssid_ie;
7589 char ssid[NDIS_802_11_LENGTH_SSID + 1];
7590 sint ssid_len = 0;
7591 u8 ignore_broadcast_ssid;
7592
7593 if (check_fwstate(mlmepriv, WIFI_AP_STATE) != _TRUE)
7594 return -EPERM;
7595
7596 if (param->u.bcn_ie.reserved[0] != 0xea)
7597 return -EINVAL;
7598
7599 mlmeinfo->hidden_ssid_mode = ignore_broadcast_ssid = param->u.bcn_ie.reserved[1];
7600
7601 ie_len = len - 12 - 2; /* 12 = param header, 2:no packed */
7602 ssid_ie = rtw_get_ie(param->u.bcn_ie.buf, WLAN_EID_SSID, &ssid_len, ie_len);
7603
7604 if (ssid_ie && ssid_len > 0 && ssid_len <= NDIS_802_11_LENGTH_SSID) {
7605 WLAN_BSSID_EX *pbss_network = &mlmepriv->cur_network.network;
7606 WLAN_BSSID_EX *pbss_network_ext = &mlmeinfo->network;
7607
7608 _rtw_memcpy(ssid, ssid_ie + 2, ssid_len);
7609 ssid[ssid_len] = 0x0;
7610
7611 if (0)
7612 RTW_INFO(FUNC_ADPT_FMT" ssid:(%s,%d), from ie:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),
7613 ssid, ssid_len,
7614 pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,
7615 pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);
7616
7617 _rtw_memcpy(pbss_network->Ssid.Ssid, (void *)ssid, ssid_len);
7618 pbss_network->Ssid.SsidLength = ssid_len;
7619 _rtw_memcpy(pbss_network_ext->Ssid.Ssid, (void *)ssid, ssid_len);
7620 pbss_network_ext->Ssid.SsidLength = ssid_len;
7621
7622 if (0)
7623 RTW_INFO(FUNC_ADPT_FMT" after ssid:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),
7624 pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,
7625 pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);
7626 }
7627
7628 RTW_INFO(FUNC_ADPT_FMT" ignore_broadcast_ssid:%d, %s,%d\n", FUNC_ADPT_ARG(adapter),
7629 ignore_broadcast_ssid, ssid, ssid_len);
7630
7631 return ret;
7632 }
7633
7634 #if CONFIG_RTW_MACADDR_ACL
7635 static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
7636 {
7637 int ret = 0;
7638 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7639 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7640
7641 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
7642 return -EINVAL;
7643
7644 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
7645 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
7646 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
7647 return -EINVAL;
7648
7649 ret = rtw_acl_remove_sta(padapter, RTW_ACL_PERIOD_BSS, param->sta_addr);
7650
7651 return ret;
7652
7653 }
7654
7655 static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
7656 {
7657 int ret = 0;
7658 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7659 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7660
7661 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
7662 return -EINVAL;
7663
7664 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
7665 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
7666 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
7667 return -EINVAL;
7668
7669 ret = rtw_acl_add_sta(padapter, RTW_ACL_PERIOD_BSS, param->sta_addr);
7670
7671 return ret;
7672
7673 }
7674
7675 static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
7676 {
7677 int ret = 0;
7678 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7679 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7680
7681 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
7682 return -EINVAL;
7683
7684 rtw_set_macaddr_acl(padapter, RTW_ACL_PERIOD_BSS, param->u.mlme.command);
7685
7686 return ret;
7687 }
7688 #endif /* CONFIG_RTW_MACADDR_ACL */
7689
7690 static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
7691 {
7692 struct ieee_param *param;
7693 int ret = 0;
7694 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7695
7696 /* RTW_INFO("%s\n", __FUNCTION__); */
7697
7698 /*
7699 * this function is expect to call in master mode, which allows no power saving
7700 * so, we just check hw_init_completed
7701 */
7702
7703 if (!rtw_is_hw_init_completed(padapter)) {
7704 ret = -EPERM;
7705 goto out;
7706 }
7707
7708
7709 /* if (p->length < sizeof(struct ieee_param) || !p->pointer){ */
7710 if (!p->pointer) {
7711 ret = -EINVAL;
7712 goto out;
7713 }
7714
7715 param = (struct ieee_param *)rtw_malloc(p->length);
7716 if (param == NULL) {
7717 ret = -ENOMEM;
7718 goto out;
7719 }
7720
7721 if (copy_from_user(param, p->pointer, p->length)) {
7722 rtw_mfree((u8 *)param, p->length);
7723 ret = -EFAULT;
7724 goto out;
7725 }
7726
7727 /* RTW_INFO("%s, cmd=%d\n", __FUNCTION__, param->cmd); */
7728
7729 switch (param->cmd) {
7730 case RTL871X_HOSTAPD_FLUSH:
7731
7732 ret = rtw_hostapd_sta_flush(dev);
7733
7734 break;
7735
7736 case RTL871X_HOSTAPD_ADD_STA:
7737
7738 ret = rtw_add_sta(dev, param);
7739
7740 break;
7741
7742 case RTL871X_HOSTAPD_REMOVE_STA:
7743
7744 ret = rtw_del_sta(dev, param);
7745
7746 break;
7747
7748 case RTL871X_HOSTAPD_SET_BEACON:
7749
7750 ret = rtw_set_beacon(dev, param, p->length);
7751
7752 break;
7753
7754 case RTL871X_SET_ENCRYPTION:
7755
7756 ret = rtw_set_encryption(dev, param, p->length);
7757
7758 break;
7759
7760 case RTL871X_HOSTAPD_GET_WPAIE_STA:
7761
7762 ret = rtw_get_sta_wpaie(dev, param);
7763
7764 break;
7765
7766 case RTL871X_HOSTAPD_SET_WPS_BEACON:
7767
7768 ret = rtw_set_wps_beacon(dev, param, p->length);
7769
7770 break;
7771
7772 case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
7773
7774 ret = rtw_set_wps_probe_resp(dev, param, p->length);
7775
7776 break;
7777
7778 case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
7779
7780 ret = rtw_set_wps_assoc_resp(dev, param, p->length);
7781
7782 break;
7783
7784 case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
7785
7786 ret = rtw_set_hidden_ssid(dev, param, p->length);
7787
7788 break;
7789
7790 case RTL871X_HOSTAPD_GET_INFO_STA:
7791
7792 ret = rtw_ioctl_get_sta_data(dev, param, p->length);
7793
7794 break;
7795
7796 #if CONFIG_RTW_MACADDR_ACL
7797 case RTL871X_HOSTAPD_SET_MACADDR_ACL:
7798 ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
7799 break;
7800 case RTL871X_HOSTAPD_ACL_ADD_STA:
7801 ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
7802 break;
7803 case RTL871X_HOSTAPD_ACL_REMOVE_STA:
7804 ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
7805 break;
7806 #endif /* CONFIG_RTW_MACADDR_ACL */
7807
7808 default:
7809 RTW_INFO("Unknown hostapd request: %d\n", param->cmd);
7810 ret = -EOPNOTSUPP;
7811 break;
7812
7813 }
7814
7815 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
7816 ret = -EFAULT;
7817
7818
7819 rtw_mfree((u8 *)param, p->length);
7820
7821 out:
7822
7823 return ret;
7824
7825 }
7826 #endif /* CONFIG_AP_MODE */
7827
7828 static int rtw_wx_set_priv(struct net_device *dev,
7829 struct iw_request_info *info,
7830 union iwreq_data *awrq,
7831 char *extra)
7832 {
7833
7834 #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
7835 char *ext_dbg;
7836 #endif
7837
7838 int ret = 0;
7839 int len = 0;
7840 char *ext;
7841 #ifdef CONFIG_RTW_ANDROID
7842 int i;
7843 #endif
7844
7845 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
7846 struct iw_point *dwrq = (struct iw_point *)awrq;
7847
7848 if (dwrq->length == 0)
7849 return -EFAULT;
7850
7851 len = dwrq->length;
7852 ext = rtw_vmalloc(len);
7853 if (!ext)
7854 return -ENOMEM;
7855
7856 if (copy_from_user(ext, dwrq->pointer, len)) {
7857 rtw_vmfree(ext, len);
7858 return -EFAULT;
7859 }
7860
7861
7862
7863 #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
7864 ext_dbg = rtw_vmalloc(len);
7865 if (!ext_dbg) {
7866 rtw_vmfree(ext, len);
7867 return -ENOMEM;
7868 }
7869
7870 _rtw_memcpy(ext_dbg, ext, len);
7871 #endif
7872
7873 /* added for wps2.0 @20110524 */
7874 if (dwrq->flags == 0x8766 && len > 8) {
7875 u32 cp_sz;
7876 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7877 u8 *probereq_wpsie = ext;
7878 int probereq_wpsie_len = len;
7879 u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
7880
7881 if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
7882 (_rtw_memcmp(&probereq_wpsie[2], wps_oui, 4) == _TRUE)) {
7883 cp_sz = probereq_wpsie_len > MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN : probereq_wpsie_len;
7884
7885 if (pmlmepriv->wps_probe_req_ie) {
7886 u32 free_len = pmlmepriv->wps_probe_req_ie_len;
7887 pmlmepriv->wps_probe_req_ie_len = 0;
7888 rtw_mfree(pmlmepriv->wps_probe_req_ie, free_len);
7889 pmlmepriv->wps_probe_req_ie = NULL;
7890 }
7891
7892 pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
7893 if (pmlmepriv->wps_probe_req_ie == NULL) {
7894 printk("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
7895 ret = -EINVAL;
7896 goto FREE_EXT;
7897
7898 }
7899
7900 _rtw_memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
7901 pmlmepriv->wps_probe_req_ie_len = cp_sz;
7902
7903 }
7904
7905 goto FREE_EXT;
7906
7907 }
7908
7909 if (len >= WEXT_CSCAN_HEADER_SIZE
7910 && _rtw_memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE) == _TRUE
7911 ) {
7912 ret = rtw_wx_set_scan(dev, info, awrq, ext);
7913 goto FREE_EXT;
7914 }
7915
7916 #ifdef CONFIG_RTW_ANDROID
7917 /* RTW_INFO("rtw_wx_set_priv: %s req=%s\n", dev->name, ext); */
7918
7919 i = rtw_android_cmdstr_to_num(ext);
7920
7921 switch (i) {
7922 case ANDROID_WIFI_CMD_START:
7923 indicate_wx_custom_event(padapter, "START");
7924 break;
7925 case ANDROID_WIFI_CMD_STOP:
7926 indicate_wx_custom_event(padapter, "STOP");
7927 break;
7928 case ANDROID_WIFI_CMD_RSSI: {
7929 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7930 struct wlan_network *pcur_network = &pmlmepriv->cur_network;
7931
7932 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
7933 sprintf(ext, "%s rssi %d", pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
7934 else
7935 sprintf(ext, "OK");
7936 }
7937 break;
7938 case ANDROID_WIFI_CMD_LINKSPEED: {
7939 u16 mbps = rtw_get_cur_max_rate(padapter) / 10;
7940 sprintf(ext, "LINKSPEED %d", mbps);
7941 }
7942 break;
7943 case ANDROID_WIFI_CMD_MACADDR:
7944 sprintf(ext, "MACADDR = " MAC_FMT, MAC_ARG(dev->dev_addr));
7945 break;
7946 case ANDROID_WIFI_CMD_SCAN_ACTIVE: {
7947 /* rtw_set_scan_mode(padapter, SCAN_ACTIVE); */
7948 sprintf(ext, "OK");
7949 }
7950 break;
7951 case ANDROID_WIFI_CMD_SCAN_PASSIVE: {
7952 /* rtw_set_scan_mode(padapter, SCAN_PASSIVE); */
7953 sprintf(ext, "OK");
7954 }
7955 break;
7956
7957 case ANDROID_WIFI_CMD_COUNTRY: {
7958 char country_code[10];
7959 sscanf(ext, "%*s %s", country_code);
7960 rtw_set_country(padapter, country_code);
7961 sprintf(ext, "OK");
7962 }
7963 break;
7964 default:
7965 #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
7966 RTW_INFO("%s: %s unknowned req=%s\n", __FUNCTION__,
7967 dev->name, ext_dbg);
7968 #endif
7969
7970 sprintf(ext, "OK");
7971
7972 }
7973
7974 if (copy_to_user(dwrq->pointer, ext, min(dwrq->length, (u16)(strlen(ext) + 1))))
7975 ret = -EFAULT;
7976
7977 #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
7978 RTW_INFO("%s: %s req=%s rep=%s dwrq->length=%d, strlen(ext)+1=%d\n", __FUNCTION__,
7979 dev->name, ext_dbg , ext, dwrq->length, (u16)(strlen(ext) + 1));
7980 #endif
7981 #endif /* end of CONFIG_ANDROID */
7982
7983
7984 FREE_EXT:
7985
7986 rtw_vmfree(ext, len);
7987 #ifdef CONFIG_DEBUG_RTW_WX_SET_PRIV
7988 rtw_vmfree(ext_dbg, len);
7989 #endif
7990
7991 /* RTW_INFO("rtw_wx_set_priv: (SIOCSIWPRIV) %s ret=%d\n", */
7992 /* dev->name, ret); */
7993
7994 return ret;
7995
7996 }
7997 #endif /*CONFIG_IOCTL_WEXT*/
7998
7999 #ifdef CONFIG_WOWLAN
8000 static int rtw_wowlan_ctrl(struct net_device *dev,
8001 struct iw_request_info *info,
8002 union iwreq_data *wrqu, char *extra)
8003 {
8004 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8005 struct wowlan_ioctl_param poidparam;
8006 struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
8007 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
8008 int ret = 0;
8009 systime start_time = rtw_get_current_time();
8010 poidparam.subcode = 0;
8011
8012 RTW_INFO("+rtw_wowlan_ctrl: %s\n", extra);
8013
8014 if (!check_fwstate(pmlmepriv, WIFI_ASOC_STATE) &&
8015 check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
8016 !WOWLAN_IS_STA_MIX_MODE(padapter)) {
8017 #ifdef CONFIG_PNO_SUPPORT
8018 pwrctrlpriv->wowlan_pno_enable = _TRUE;
8019 #else
8020 RTW_INFO("[%s] WARNING: Please Connect With AP First!!\n", __func__);
8021 goto _rtw_wowlan_ctrl_exit_free;
8022 #endif /* CONFIG_PNO_SUPPORT */
8023 }
8024
8025 if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY))
8026 rtw_scan_abort(padapter);
8027
8028 if (_rtw_memcmp(extra, "enable", 6))
8029
8030
8031 rtw_suspend_common(padapter);
8032
8033 else if (_rtw_memcmp(extra, "disable", 7)) {
8034 #ifdef CONFIG_USB_HCI
8035 RTW_ENABLE_FUNC(padapter, DF_RX_BIT);
8036 RTW_ENABLE_FUNC(padapter, DF_TX_BIT);
8037 #endif
8038 rtw_resume_common(padapter);
8039
8040 #ifdef CONFIG_PNO_SUPPORT
8041 pwrctrlpriv->wowlan_pno_enable = _FALSE;
8042 #endif /* CONFIG_PNO_SUPPORT */
8043
8044 } else {
8045 RTW_INFO("[%s] Invalid Parameter.\n", __func__);
8046 goto _rtw_wowlan_ctrl_exit_free;
8047 }
8048 /* mutex_lock(&ioctl_mutex); */
8049 _rtw_wowlan_ctrl_exit_free:
8050 RTW_INFO("-rtw_wowlan_ctrl( subcode = %d)\n", poidparam.subcode);
8051 RTW_PRINT("%s in %d ms\n", __func__,
8052 rtw_get_passing_time_ms(start_time));
8053 return ret;
8054 }
8055
8056 /*
8057 * IP filter This pattern if for a frame containing a ip packet:
8058 * AA:AA:AA:AA:AA:AA:BB:BB:BB:BB:BB:BB:CC:CC:DD:-:-:-:-:-:-:-:-:EE:-:-:FF:FF:FF:FF:GG:GG:GG:GG:HH:HH:II:II
8059 *
8060 * A: Ethernet destination address
8061 * B: Ethernet source address
8062 * C: Ethernet protocol type
8063 * D: IP header VER+Hlen, use: 0x45 (4 is for ver 4, 5 is for len 20)
8064 * E: IP protocol
8065 * F: IP source address ( 192.168.0.4: C0:A8:00:2C )
8066 * G: IP destination address ( 192.168.0.4: C0:A8:00:2C )
8067 * H: Source port (1024: 04:00)
8068 * I: Destination port (1024: 04:00)
8069 */
8070
8071 static int rtw_wowlan_set_pattern(struct net_device *dev,
8072 struct iw_request_info *info,
8073 union iwreq_data *wrqu, char *extra)
8074 {
8075 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8076 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
8077 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
8078 struct wowlan_ioctl_param poidparam;
8079 int ret = 0;
8080 u8 input[MAX_IN_PATTERN_SIZE];
8081 u8 index = 0;
8082
8083 poidparam.subcode = 0;
8084
8085 if (!check_fwstate(pmlmepriv, WIFI_ASOC_STATE) &&
8086 check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
8087 ret = -EFAULT;
8088 RTW_INFO("Please Connect With AP First!!\n");
8089 goto _rtw_wowlan_set_pattern_exit;
8090 }
8091
8092 if ((wrqu->data.length <= 0) || (wrqu->data.length > MAX_IN_PATTERN_SIZE)) {
8093 ret = -EFAULT;
8094 RTW_INFO("ERROR: parameter length error, len=%d\n", wrqu->data.length);
8095 goto _rtw_wowlan_set_pattern_exit;
8096 } else {
8097 /* set pattern */
8098 if (copy_from_user(input,
8099 wrqu->data.pointer, wrqu->data.length))
8100 return -EFAULT;
8101 /* leave PS first */
8102 rtw_ps_deny(padapter, PS_DENY_IOCTL);
8103 LeaveAllPowerSaveModeDirect(padapter);
8104 if (strncmp(input, "pattern=", 8) == 0) {
8105 if (pwrpriv->wowlan_pattern_idx >= MAX_WKFM_CAM_NUM) {
8106 RTW_INFO("WARNING: priv-pattern is full(idx: %d)\n",
8107 pwrpriv->wowlan_pattern_idx);
8108 RTW_INFO("WARNING: please clean priv-pattern first\n");
8109 ret = -EINVAL;
8110 goto _rtw_wowlan_set_pattern_exit;
8111 } else {
8112 index = pwrpriv->wowlan_pattern_idx;
8113 ret = rtw_wowlan_parser_pattern_cmd(input,
8114 pwrpriv->patterns[index].content,
8115 &pwrpriv->patterns[index].len,
8116 pwrpriv->patterns[index].mask);
8117
8118 if (ret == _TRUE)
8119 pwrpriv->wowlan_pattern_idx++;
8120 }
8121 } else if (strncmp(input, "clean", 5) == 0) {
8122 poidparam.subcode = WOWLAN_PATTERN_CLEAN;
8123 rtw_hal_set_hwreg(padapter,
8124 HW_VAR_WOWLAN, (u8 *)&poidparam);
8125 } else if (strncmp(input, "show", 4) == 0) {
8126 rtw_wow_pattern_cam_dump(padapter);
8127 rtw_wow_pattern_sw_dump(padapter);
8128 } else {
8129 RTW_INFO("ERROR: incorrect parameter!\n");
8130 ret = -EINVAL;
8131 }
8132 rtw_ps_deny_cancel(padapter, PS_DENY_IOCTL);
8133 }
8134 _rtw_wowlan_set_pattern_exit:
8135 return ret;
8136 }
8137 #endif /* CONFIG_WOWLAN */
8138
8139 #ifdef CONFIG_AP_WOWLAN
8140 static int rtw_ap_wowlan_ctrl(struct net_device *dev,
8141 struct iw_request_info *info,
8142 union iwreq_data *wrqu, char *extra)
8143 {
8144 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8145 struct wowlan_ioctl_param poidparam;
8146 struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
8147 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
8148 struct sta_info *psta = NULL;
8149 int ret = 0;
8150 systime start_time = rtw_get_current_time();
8151 poidparam.subcode = 0;
8152
8153 RTW_INFO("+rtw_ap_wowlan_ctrl: %s\n", extra);
8154
8155 if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
8156 RTW_INFO("[%s] It is not AP mode!!\n", __func__);
8157 goto _rtw_ap_wowlan_ctrl_exit_free;
8158 }
8159
8160 if (_rtw_memcmp(extra, "enable", 6)) {
8161
8162 pwrctrlpriv->wowlan_ap_mode = _TRUE;
8163
8164 rtw_suspend_common(padapter);
8165 } else if (_rtw_memcmp(extra, "disable", 7)) {
8166 #ifdef CONFIG_USB_HCI
8167 RTW_ENABLE_FUNC(padapter, DF_RX_BIT);
8168 RTW_ENABLE_FUNC(padapter, DF_TX_BIT);
8169 #endif
8170 rtw_resume_common(padapter);
8171 } else {
8172 RTW_INFO("[%s] Invalid Parameter.\n", __func__);
8173 goto _rtw_ap_wowlan_ctrl_exit_free;
8174 }
8175 /* mutex_lock(&ioctl_mutex); */
8176 _rtw_ap_wowlan_ctrl_exit_free:
8177 RTW_INFO("-rtw_ap_wowlan_ctrl( subcode = %d)\n", poidparam.subcode);
8178 RTW_PRINT("%s in %d ms\n", __func__,
8179 rtw_get_passing_time_ms(start_time));
8180 _rtw_ap_wowlan_ctrl_exit:
8181 return ret;
8182 }
8183 #endif /* CONFIG_AP_WOWLAN */
8184
8185 static int rtw_pm_set(struct net_device *dev,
8186 struct iw_request_info *info,
8187 union iwreq_data *wrqu, char *extra)
8188 {
8189 int ret = 0;
8190 unsigned mode = 0;
8191 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8192
8193 RTW_INFO("[%s] extra = %s\n", __FUNCTION__, extra);
8194
8195 if (_rtw_memcmp(extra, "lps=", 4)) {
8196 sscanf(extra + 4, "%u", &mode);
8197 ret = rtw_pm_set_lps(padapter, mode);
8198 } else if (_rtw_memcmp(extra, "ips=", 4)) {
8199 sscanf(extra + 4, "%u", &mode);
8200 ret = rtw_pm_set_ips(padapter, mode);
8201 } else if (_rtw_memcmp(extra, "lps_level=", 10)) {
8202 if (sscanf(extra + 10, "%u", &mode) > 0)
8203 ret = rtw_pm_set_lps_level(padapter, mode);
8204 #ifdef CONFIG_LPS_1T1R
8205 } else if (_rtw_memcmp(extra, "lps_1t1r=", 9)) {
8206 if (sscanf(extra + 9, "%u", &mode) > 0)
8207 ret = rtw_pm_set_lps_1t1r(padapter, mode);
8208 #endif
8209 }
8210 #ifdef CONFIG_WOWLAN
8211 else if (_rtw_memcmp(extra, "wow_lps=", 8)) {
8212 sscanf(extra + 8, "%u", &mode);
8213 ret = rtw_pm_set_wow_lps(padapter, mode);
8214 } else if (_rtw_memcmp(extra, "wow_lps_level=", 14)) {
8215 if (sscanf(extra + 14, "%u", &mode) > 0)
8216 ret = rtw_pm_set_wow_lps_level(padapter, mode);
8217 #ifdef CONFIG_LPS_1T1R
8218 } else if (_rtw_memcmp(extra, "wow_lps_1t1r=", 13)) {
8219 if (sscanf(extra + 13, "%u", &mode) > 0)
8220 ret = rtw_pm_set_wow_lps_1t1r(padapter, mode);
8221 #endif
8222 }
8223 #endif /* CONFIG_WOWLAN */
8224 else
8225 ret = -EINVAL;
8226
8227 return ret;
8228 }
8229 #ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
8230
8231 int rtw_vendor_ie_get_raw_data(struct net_device *dev, u32 vendor_ie_num,
8232 char *extra, u32 length)
8233 {
8234 int j;
8235 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8236 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8237 u32 vendor_ie_mask = 0;
8238 char *pstring;
8239
8240 if (vendor_ie_num >= WLAN_MAX_VENDOR_IE_NUM) {
8241 RTW_INFO("[%s] only support %d vendor ie\n", __func__ ,
8242 WLAN_MAX_VENDOR_IE_NUM);
8243 return -EFAULT;
8244 }
8245
8246 if (pmlmepriv->vendor_ielen[vendor_ie_num] == 0) {
8247 RTW_INFO("[%s] Fail, vendor_ie_num: %d is not set\n", __func__,
8248 vendor_ie_num);
8249 return -EFAULT;
8250 }
8251
8252 if (length < 2 * pmlmepriv->vendor_ielen[vendor_ie_num] + 5) {
8253 RTW_INFO("[%s] Fail, buffer size is too small\n", __func__);
8254 return -EFAULT;
8255 }
8256
8257 vendor_ie_mask = pmlmepriv->vendor_ie_mask[vendor_ie_num];
8258 _rtw_memset(extra, 0, length);
8259
8260 pstring = extra;
8261 pstring += sprintf(pstring, "%d,%x,", vendor_ie_num, vendor_ie_mask);
8262
8263 for (j = 0; j < pmlmepriv->vendor_ielen[vendor_ie_num]; j++)
8264 pstring += sprintf(pstring, "%02x", pmlmepriv->vendor_ie[vendor_ie_num][j]);
8265
8266 length = pstring - extra;
8267 return length;
8268 }
8269
8270 int rtw_vendor_ie_get_data(struct net_device *dev, int vendor_ie_num, char *extra)
8271 {
8272 int j;
8273 char *pstring;
8274 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8275 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8276 u32 vendor_ie_mask = 0;
8277 __u16 length = 0;
8278
8279 vendor_ie_mask = pmlmepriv->vendor_ie_mask[vendor_ie_num];
8280 pstring = extra;
8281 pstring += sprintf(pstring , "\nVendor IE num %d , Mask:%x " , vendor_ie_num , vendor_ie_mask);
8282
8283 if (vendor_ie_mask & WIFI_BEACON_VENDOR_IE_BIT)
8284 pstring += sprintf(pstring , "[Beacon]");
8285 if (vendor_ie_mask & WIFI_PROBEREQ_VENDOR_IE_BIT)
8286 pstring += sprintf(pstring , "[Probe Req]");
8287 if (vendor_ie_mask & WIFI_PROBERESP_VENDOR_IE_BIT)
8288 pstring += sprintf(pstring , "[Probe Resp]");
8289 if (vendor_ie_mask & WIFI_ASSOCREQ_VENDOR_IE_BIT)
8290 pstring += sprintf(pstring , "[Assoc Req]");
8291 if (vendor_ie_mask & WIFI_ASSOCRESP_VENDOR_IE_BIT)
8292 pstring += sprintf(pstring , "[Assoc Resp]");
8293 #ifdef CONFIG_P2P
8294 if (vendor_ie_mask & WIFI_P2P_PROBEREQ_VENDOR_IE_BIT)
8295 pstring += sprintf(pstring , "[P2P_Probe Req]");
8296 if (vendor_ie_mask & WIFI_P2P_PROBERESP_VENDOR_IE_BIT)
8297 pstring += sprintf(pstring , "[P2P_Probe Resp]");
8298 #endif
8299
8300 pstring += sprintf(pstring , "\nVendor IE:\n");
8301 for (j = 0 ; j < pmlmepriv->vendor_ielen[vendor_ie_num] ; j++)
8302 pstring += sprintf(pstring , "%02x" , pmlmepriv->vendor_ie[vendor_ie_num][j]);
8303
8304 length = pstring - extra;
8305 return length;
8306
8307 }
8308
8309 int rtw_vendor_ie_get(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
8310 {
8311 int ret = 0, vendor_ie_num = 0, cmdlen;
8312 struct iw_point *p;
8313 u8 *ptmp;
8314
8315 p = &wrqu->data;
8316 cmdlen = p->length;
8317 if (0 == cmdlen)
8318 return -EINVAL;
8319
8320 ptmp = (u8 *)rtw_malloc(cmdlen);
8321 if (NULL == ptmp)
8322 return -ENOMEM;
8323
8324 if (copy_from_user(ptmp, p->pointer, cmdlen)) {
8325 ret = -EFAULT;
8326 goto exit;
8327 }
8328 ret = sscanf(ptmp , "%d", &vendor_ie_num);
8329 if (vendor_ie_num > WLAN_MAX_VENDOR_IE_NUM - 1) {
8330 ret = -EFAULT;
8331 goto exit;
8332 }
8333
8334 wrqu->data.length = rtw_vendor_ie_get_data(dev, vendor_ie_num, extra);
8335
8336 exit:
8337 rtw_mfree(ptmp, cmdlen);
8338
8339 return 0;
8340 }
8341
8342 int rtw_vendor_ie_set(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
8343 {
8344 int ret = 0, i , len = 0 , totoal_ie_len = 0 , total_ie_len_byte = 0;
8345 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
8346 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
8347 u32 vendor_ie_mask = 0;
8348 u32 vendor_ie_num = 0;
8349 u32 vendor_ie_mask_max = BIT(WLAN_MAX_VENDOR_IE_MASK_MAX) - 1;
8350 u32 id, elen;
8351
8352 ret = sscanf(extra, "%d,%x,%*s", &vendor_ie_num , &vendor_ie_mask);
8353 if (strrchr(extra , ','))
8354 extra = strrchr(extra , ',') + 1;
8355 else
8356 return -EINVAL;
8357 totoal_ie_len = strlen(extra);
8358 RTW_INFO("[%s] vendor_ie_num = %d , vendor_ie_mask = 0x%x , vendor_ie = %s , len = %d\n", __func__ , vendor_ie_num , vendor_ie_mask , extra , totoal_ie_len);
8359
8360 if (vendor_ie_num > WLAN_MAX_VENDOR_IE_NUM - 1) {
8361 RTW_INFO("[%s] Fail, only support %d vendor ie\n", __func__ , WLAN_MAX_VENDOR_IE_NUM);
8362 return -EFAULT;
8363 }
8364
8365 if (totoal_ie_len > WLAN_MAX_VENDOR_IE_LEN) {
8366 RTW_INFO("[%s] Fail , not support ie length extend %d\n", __func__ , WLAN_MAX_VENDOR_IE_LEN);
8367 return -EFAULT;
8368 }
8369
8370 if (vendor_ie_mask > vendor_ie_mask_max) {
8371 RTW_INFO("[%s] Fail, not support vendor_ie_mask more than 0x%x\n", __func__ , vendor_ie_mask_max);
8372 return -EFAULT;
8373 }
8374
8375 if (vendor_ie_mask == 0) {
8376 RTW_INFO("[%s] Clear vendor_ie_num %d group\n", __func__ , vendor_ie_num);
8377 goto _clear_path;
8378 }
8379
8380 if (totoal_ie_len % 2 != 0) {
8381 RTW_INFO("[%s] Fail , IE length = %zu is odd\n" , __func__ , strlen(extra));
8382 return -EFAULT;
8383 }
8384
8385 if (totoal_ie_len > 0) {
8386 for (i = 0 ; i < strlen(extra) ; i += 2) {
8387 pmlmepriv->vendor_ie[vendor_ie_num][len] = key_2char2num(extra[i] , extra[i + 1]);
8388 if (len == 0) {
8389 id = pmlmepriv->vendor_ie[vendor_ie_num][len];
8390 if (id != WLAN_EID_VENDOR_SPECIFIC) {
8391 RTW_INFO("[%s] Fail , VENDOR SPECIFIC IE ID \"%x\" was not correct\n", __func__ , id);
8392 goto _clear_path;
8393 }
8394 } else if (len == 1) {
8395 total_ie_len_byte = (totoal_ie_len / 2) - 2;
8396 elen = pmlmepriv->vendor_ie[vendor_ie_num][len];
8397 if (elen != total_ie_len_byte) {
8398 RTW_INFO("[%s] Fail , Input IE length = \"%d\"(hex:%x) bytes , not match input total IE context length \"%d\" bytes\n", __func__ , elen , elen ,
8399 total_ie_len_byte);
8400 goto _clear_path;
8401 }
8402 }
8403 len++;
8404 }
8405 pmlmepriv->vendor_ielen[vendor_ie_num] = len;
8406 } else
8407 pmlmepriv->vendor_ielen[vendor_ie_num] = 0;
8408
8409
8410
8411 if (vendor_ie_mask & WIFI_BEACON_VENDOR_IE_BIT)
8412 RTW_INFO("[%s] Beacon append vendor ie\n", __func__);
8413 if (vendor_ie_mask & WIFI_PROBEREQ_VENDOR_IE_BIT)
8414 RTW_INFO("[%s] Probe Req append vendor ie\n", __func__);
8415 if (vendor_ie_mask & WIFI_PROBERESP_VENDOR_IE_BIT)
8416 RTW_INFO("[%s] Probe Resp append vendor ie\n", __func__);
8417 if (vendor_ie_mask & WIFI_ASSOCREQ_VENDOR_IE_BIT)
8418 RTW_INFO("[%s] Assoc Req append vendor ie\n", __func__);
8419 if (vendor_ie_mask & WIFI_ASSOCRESP_VENDOR_IE_BIT)
8420 RTW_INFO("[%s] Assoc Resp append vendor ie\n", __func__);
8421 #ifdef CONFIG_P2P
8422 if (vendor_ie_mask & WIFI_P2P_PROBEREQ_VENDOR_IE_BIT)
8423 RTW_INFO("[%s] P2P Probe Req append vendor ie\n", __func__);
8424 if (vendor_ie_mask & WIFI_P2P_PROBERESP_VENDOR_IE_BIT)
8425 RTW_INFO("[%s] P2P Probe Resp append vendor ie\n", __func__);
8426 #endif
8427
8428 pmlmepriv->vendor_ie_mask[vendor_ie_num] = vendor_ie_mask;
8429
8430 return ret;
8431
8432 _clear_path:
8433 _rtw_memset(pmlmepriv->vendor_ie[vendor_ie_num] , 0 , sizeof(u32) * WLAN_MAX_VENDOR_IE_LEN);
8434 pmlmepriv->vendor_ielen[vendor_ie_num] = 0;
8435 pmlmepriv->vendor_ie_mask[vendor_ie_num] = 0;
8436 return -EFAULT;
8437 }
8438 #endif
8439
8440 static int rtw_mp_efuse_get(struct net_device *dev,
8441 struct iw_request_info *info,
8442 union iwreq_data *wdata, char *extra)
8443 {
8444 PADAPTER padapter = rtw_netdev_priv(dev);
8445 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
8446
8447 PEFUSE_HAL pEfuseHal;
8448 struct iw_point *wrqu;
8449
8450 u8 ips_mode = IPS_NUM; /* init invalid value */
8451 u8 lps_mode = PS_MODE_NUM; /* init invalid value */
8452 struct pwrctrl_priv *pwrctrlpriv ;
8453 u8 *data = NULL;
8454 u8 *rawdata = NULL;
8455 char *pch, *ptmp, *token, *tmp[3] = {0x00, 0x00, 0x00};
8456 u16 i = 0, j = 0, mapLen = 0, addr = 0, cnts = 0;
8457 u16 max_available_len = 0, raw_cursize = 0, raw_maxsize = 0;
8458 u16 mask_len;
8459 u8 mask_buf[64] = "";
8460 int err;
8461 char *pextra = NULL;
8462 #ifdef CONFIG_IOL
8463 u8 org_fw_iol = padapter->registrypriv.fw_iol;/* 0:Disable, 1:enable, 2:by usb speed */
8464 #endif
8465
8466 wrqu = (struct iw_point *)wdata;
8467 pwrctrlpriv = adapter_to_pwrctl(padapter);
8468 pEfuseHal = &pHalData->EfuseHal;
8469
8470 err = 0;
8471 data = rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN);
8472 if (data == NULL) {
8473 err = -ENOMEM;
8474 goto exit;
8475 }
8476 rawdata = rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN);
8477 if (rawdata == NULL) {
8478 err = -ENOMEM;
8479 goto exit;
8480 }
8481
8482 if (copy_from_user(extra, wrqu->pointer, wrqu->length)) {
8483 err = -EFAULT;
8484 goto exit;
8485 }
8486
8487 *(extra + wrqu->length) = '\0';
8488
8489 #ifdef CONFIG_LPS
8490 lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */
8491 rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
8492 #endif
8493
8494 #ifdef CONFIG_IPS
8495 ips_mode = pwrctrlpriv->ips_mode;/* keep org value */
8496 rtw_pm_set_ips(padapter, IPS_NONE);
8497 #endif
8498
8499 pch = extra;
8500 RTW_INFO("%s: in=%s\n", __FUNCTION__, extra);
8501
8502 i = 0;
8503 /* mac 16 "00e04c871200" rmap,00,2 */
8504 while ((token = strsep(&pch, ",")) != NULL) {
8505 if (i > 2)
8506 break;
8507 tmp[i] = token;
8508 i++;
8509 }
8510 #ifdef CONFIG_IOL
8511 padapter->registrypriv.fw_iol = 0;/* 0:Disable, 1:enable, 2:by usb speed */
8512 #endif
8513
8514 if (strcmp(tmp[0], "status") == 0) {
8515 sprintf(extra, "Load File efuse=%s,Load File MAC=%s"
8516 , pHalData->efuse_file_status == EFUSE_FILE_FAILED ? "FAIL" : "OK"
8517 , pHalData->macaddr_file_status == MACADDR_FILE_FAILED ? "FAIL" : "OK"
8518 );
8519 goto exit;
8520 } else if (strcmp(tmp[0], "drvmap") == 0) {
8521 static u8 drvmaporder = 0;
8522 u8 *efuse;
8523 u32 shift, cnt;
8524 u32 blksz = 0x200; /* The size of one time show, default 512 */
8525 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, _FALSE);
8526
8527 efuse = pHalData->efuse_eeprom_data;
8528
8529 shift = blksz * drvmaporder;
8530 efuse += shift;
8531 cnt = mapLen - shift;
8532
8533 if (cnt > blksz) {
8534 cnt = blksz;
8535 drvmaporder++;
8536 } else
8537 drvmaporder = 0;
8538
8539 sprintf(extra, "\n");
8540 for (i = 0; i < cnt; i += 16) {
8541 pextra = extra + strlen(extra);
8542 pextra += sprintf(pextra, "0x%02x\t", shift + i);
8543 for (j = 0; j < 8; j++)
8544 pextra += sprintf(pextra, "%02X ", efuse[i + j]);
8545 pextra += sprintf(pextra, "\t");
8546 for (; j < 16; j++)
8547 pextra += sprintf(pextra, "%02X ", efuse[i + j]);
8548 pextra += sprintf(pextra, "\n");
8549 }
8550 if ((shift + cnt) < mapLen)
8551 pextra += sprintf(pextra, "\t...more (left:%d/%d)\n", mapLen-(shift + cnt), mapLen);
8552
8553 } else if (strcmp(tmp[0], "realmap") == 0) {
8554 static u8 order = 0;
8555 u8 *efuse;
8556 u32 shift, cnt;
8557 u32 blksz = 0x200; /* The size of one time show, default 512 */
8558
8559 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN , (void *)&mapLen, _FALSE);
8560 efuse = pEfuseHal->fakeEfuseInitMap;
8561 if (rtw_efuse_mask_map_read(padapter, 0, mapLen, efuse) == _FAIL) {
8562 RTW_INFO("%s: read realmap Fail!!\n", __FUNCTION__);
8563 err = -EFAULT;
8564 goto exit;
8565 }
8566
8567 #if 0
8568 RTW_INFO("OFFSET\tVALUE(hex)\n");
8569 for (i = 0; i < mapLen; i += 16) {
8570 RTW_INFO("0x%02x\t", i);
8571 for (j = 0; j < 8; j++)
8572 RTW_INFO("%02X ", efuse[i + j]);
8573 RTW_INFO("\t");
8574 for (; j < 16; j++)
8575 RTW_INFO("%02X ", efuse[i + j]);
8576 RTW_INFO("\n");
8577 }
8578 RTW_INFO("\n");
8579 #endif
8580
8581 shift = blksz * order;
8582 efuse += shift;
8583 cnt = mapLen - shift;
8584 if (cnt > blksz) {
8585 cnt = blksz;
8586 order++;
8587 } else
8588 order = 0;
8589
8590 sprintf(extra, "\n");
8591 for (i = 0; i < cnt; i += 16) {
8592 pextra = extra + strlen(extra);
8593 pextra += sprintf(pextra, "0x%02x\t", shift + i);
8594 for (j = 0; j < 8; j++)
8595 pextra += sprintf(pextra, "%02X ", efuse[i + j]);
8596 pextra += sprintf(pextra, "\t");
8597 for (; j < 16; j++)
8598 pextra += sprintf(pextra, "%02X ", efuse[i + j]);
8599 pextra += sprintf(pextra, "\n");
8600 }
8601 if ((shift + cnt) < mapLen)
8602 pextra += sprintf(pextra, "\t...more (left:%d/%d)\n", mapLen-(shift + cnt), mapLen);
8603 } else if (strcmp(tmp[0], "rmap") == 0) {
8604 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
8605 RTW_INFO("%s: rmap Fail!! Parameters error!\n", __FUNCTION__);
8606 err = -EINVAL;
8607 goto exit;
8608 }
8609
8610 /* rmap addr cnts */
8611 addr = simple_strtoul(tmp[1], &ptmp, 16);
8612 RTW_INFO("%s: addr=%x\n", __FUNCTION__, addr);
8613
8614 cnts = simple_strtoul(tmp[2], &ptmp, 10);
8615 if (cnts == 0) {
8616 RTW_INFO("%s: rmap Fail!! cnts error!\n", __FUNCTION__);
8617 err = -EINVAL;
8618 goto exit;
8619 }
8620 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
8621
8622 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN , (void *)&max_available_len, _FALSE);
8623 if ((addr + cnts) > max_available_len) {
8624 RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
8625 err = -EINVAL;
8626 goto exit;
8627 }
8628
8629 if (rtw_efuse_mask_map_read(padapter, addr, cnts, data) == _FAIL) {
8630 RTW_INFO("%s: rtw_efuse_mask_map_read error!\n", __func__);
8631 err = -EFAULT;
8632 goto exit;
8633 }
8634
8635 /* RTW_INFO("%s: data={", __FUNCTION__); */
8636 *extra = 0;
8637 pextra = extra;
8638 for (i = 0; i < cnts; i++) {
8639 /* RTW_INFO("0x%02x ", data[i]); */
8640 pextra += sprintf(pextra, "0x%02X ", data[i]);
8641 }
8642 /* RTW_INFO("}\n"); */
8643 } else if (strcmp(tmp[0], "realraw") == 0) {
8644 static u8 raw_order = 0;
8645 u32 shift, cnt;
8646 u32 blksz = 0x200; /* The size of one time show, default 512 */
8647
8648 addr = 0;
8649 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN , (void *)&mapLen, _FALSE);
8650 RTW_INFO("Real content len = %d\n",mapLen );
8651
8652 if (rtw_efuse_access(padapter, _FALSE, addr, mapLen, rawdata) == _FAIL) {
8653 RTW_INFO("%s: rtw_efuse_access Fail!!\n", __func__);
8654 err = -EFAULT;
8655 goto exit;
8656 }
8657
8658 _rtw_memset(extra, '\0', strlen(extra));
8659
8660 shift = blksz * raw_order;
8661 rawdata += shift;
8662 cnt = mapLen - shift;
8663 if (cnt > blksz) {
8664 cnt = blksz;
8665 raw_order++;
8666 } else
8667 raw_order = 0;
8668
8669 sprintf(extra, "\n");
8670 for (i = 0; i < cnt; i += 16) {
8671 pextra = extra + strlen(extra);
8672 pextra += sprintf(pextra, "0x%02x\t", shift + i);
8673 for (j = 0; j < 8; j++)
8674 pextra += sprintf(pextra, "%02X ", rawdata[i + j]);
8675 pextra += sprintf(pextra, "\t");
8676 for (; j < 16; j++)
8677 pextra += sprintf(pextra, "%02X ", rawdata[i + j]);
8678 pextra += sprintf(pextra, "\n");
8679 }
8680 if ((shift + cnt) < mapLen)
8681 pextra += sprintf(pextra, "\t...more (left:%d/%d)\n", mapLen-(shift + cnt), mapLen);
8682
8683 } else if (strcmp(tmp[0], "btrealraw") == 0) {
8684 static u8 bt_raw_order = 0;
8685 u32 shift, cnt;
8686 u32 blksz = 0x200; /* The size of one time show, default 512 */
8687
8688 addr = 0;
8689 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&mapLen, _FALSE);
8690 RTW_INFO("Real content len = %d\n", mapLen);
8691 #ifdef RTW_HALMAC
8692 if (rtw_efuse_bt_access(padapter, _FALSE, 0, mapLen, rawdata) == _FAIL) {
8693 RTW_INFO("%s: rtw_efuse_access Fail!!\n", __func__);
8694 err = -EFAULT;
8695 goto exit;
8696 }
8697 #else
8698 rtw_write8(padapter, 0x35, 0x1);
8699
8700 if (rtw_efuse_access(padapter, _FALSE, addr, mapLen, rawdata) == _FAIL) {
8701 RTW_INFO("%s: rtw_efuse_access Fail!!\n", __func__);
8702 err = -EFAULT;
8703 goto exit;
8704 }
8705 #endif
8706 _rtw_memset(extra, '\0', strlen(extra));
8707
8708 shift = blksz * bt_raw_order;
8709 rawdata += shift;
8710 cnt = mapLen - shift;
8711 if (cnt > blksz) {
8712 cnt = blksz;
8713 bt_raw_order++;
8714 } else
8715 bt_raw_order = 0;
8716
8717 sprintf(extra, "\n");
8718 for (i = 0; i < cnt; i += 16) {
8719 pextra = extra + strlen(extra);
8720 pextra += sprintf(pextra, "0x%02x\t", shift + i);
8721 for (j = 0; j < 8; j++)
8722 pextra += sprintf(pextra, "%02X ", rawdata[i + j]);
8723 pextra += sprintf(pextra, "\t");
8724 for (; j < 16; j++)
8725 pextra += sprintf(pextra, "%02X ", rawdata[i + j]);
8726 pextra += sprintf(pextra, "\n");
8727 }
8728 if ((shift + cnt) < mapLen)
8729 pextra += sprintf(pextra, "\t...more (left:%d/%d)\n", mapLen-(shift + cnt), mapLen);
8730
8731 } else if (strcmp(tmp[0], "mac") == 0) {
8732 if (hal_efuse_macaddr_offset(padapter) == -1) {
8733 err = -EFAULT;
8734 goto exit;
8735 }
8736
8737 addr = hal_efuse_macaddr_offset(padapter);
8738 cnts = 6;
8739
8740 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_len, _FALSE);
8741 if ((addr + cnts) > max_available_len) {
8742 RTW_INFO("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
8743 err = -EFAULT;
8744 goto exit;
8745 }
8746
8747 if (rtw_efuse_mask_map_read(padapter, addr, cnts, data) == _FAIL) {
8748 RTW_INFO("%s: rtw_efuse_mask_map_read error!\n", __func__);
8749 err = -EFAULT;
8750 goto exit;
8751 }
8752
8753 /* RTW_INFO("%s: MAC address={", __FUNCTION__); */
8754 *extra = 0;
8755 pextra = extra;
8756 for (i = 0; i < cnts; i++) {
8757 /* RTW_INFO("%02X", data[i]); */
8758 pextra += sprintf(pextra, "%02X", data[i]);
8759 if (i != (cnts - 1)) {
8760 /* RTW_INFO(":"); */
8761 pextra += sprintf(pextra, ":");
8762 }
8763 }
8764 /* RTW_INFO("}\n"); */
8765 } else if (strcmp(tmp[0], "vidpid") == 0) {
8766 #ifdef CONFIG_RTL8188E
8767 #ifdef CONFIG_USB_HCI
8768 addr = EEPROM_VID_88EU;
8769 #endif
8770 #ifdef CONFIG_PCI_HCI
8771 addr = EEPROM_VID_88EE;
8772 #endif
8773 #endif /* CONFIG_RTL8188E */
8774
8775 #ifdef CONFIG_RTL8192E
8776 #ifdef CONFIG_USB_HCI
8777 addr = EEPROM_VID_8192EU;
8778 #endif
8779 #ifdef CONFIG_PCI_HCI
8780 addr = EEPROM_VID_8192EE;
8781 #endif
8782 #endif /* CONFIG_RTL8192E */
8783 #ifdef CONFIG_RTL8723B
8784 addr = EEPROM_VID_8723BU;
8785 #endif /* CONFIG_RTL8192E */
8786
8787 #ifdef CONFIG_RTL8188F
8788 addr = EEPROM_VID_8188FU;
8789 #endif /* CONFIG_RTL8188F */
8790
8791 #ifdef CONFIG_RTL8188GTV
8792 addr = EEPROM_VID_8188GTVU;
8793 #endif
8794
8795 #ifdef CONFIG_RTL8703B
8796 #ifdef CONFIG_USB_HCI
8797 addr = EEPROM_VID_8703BU;
8798 #endif
8799 #endif /* CONFIG_RTL8703B */
8800
8801 #ifdef CONFIG_RTL8723D
8802 #ifdef CONFIG_USB_HCI
8803 addr = EEPROM_VID_8723DU;
8804 #endif /* CONFIG_USB_HCI */
8805 #endif /* CONFIG_RTL8723D */
8806
8807 cnts = 4;
8808
8809 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_len, _FALSE);
8810 if ((addr + cnts) > max_available_len) {
8811 RTW_INFO("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
8812 err = -EFAULT;
8813 goto exit;
8814 }
8815 if (rtw_efuse_mask_map_read(padapter, addr, cnts, data) == _FAIL) {
8816 RTW_INFO("%s: rtw_efuse_access error!!\n", __FUNCTION__);
8817 err = -EFAULT;
8818 goto exit;
8819 }
8820
8821 /* RTW_INFO("%s: {VID,PID}={", __FUNCTION__); */
8822 *extra = 0;
8823 pextra = extra;
8824 for (i = 0; i < cnts; i++) {
8825 /* RTW_INFO("0x%02x", data[i]); */
8826 pextra += sprintf(pextra, "0x%02X", data[i]);
8827 if (i != (cnts - 1)) {
8828 /* RTW_INFO(","); */
8829 pextra += sprintf(pextra, ",");
8830 }
8831 }
8832 /* RTW_INFO("}\n"); */
8833 } else if (strcmp(tmp[0], "ableraw") == 0) {
8834 #ifdef RTW_HALMAC
8835 raw_maxsize = efuse_GetavailableSize(padapter);
8836 #else
8837 efuse_GetCurrentSize(padapter, &raw_cursize);
8838 raw_maxsize = efuse_GetMaxSize(padapter);
8839 #endif
8840 sprintf(extra, "[available raw size]= %d bytes\n", raw_maxsize - raw_cursize);
8841 } else if (strcmp(tmp[0], "btableraw") == 0) {
8842 efuse_bt_GetCurrentSize(padapter, &raw_cursize);
8843 raw_maxsize = efuse_bt_GetMaxSize(padapter);
8844 sprintf(extra, "[available raw size]= %d bytes\n", raw_maxsize - raw_cursize);
8845 } else if (strcmp(tmp[0], "btfmap") == 0) {
8846
8847 BTEfuse_PowerSwitch(padapter, 1, _TRUE);
8848
8849 mapLen = EFUSE_BT_MAX_MAP_LEN;
8850 if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL) {
8851 RTW_INFO("%s: rtw_BT_efuse_map_read Fail!!\n", __FUNCTION__);
8852 err = -EFAULT;
8853 goto exit;
8854 }
8855
8856 /* RTW_INFO("OFFSET\tVALUE(hex)\n"); */
8857 sprintf(extra, "\n");
8858 for (i = 0; i < 512; i += 16) { /* set 512 because the iwpriv's extra size have limit 0x7FF */
8859 /* RTW_INFO("0x%03x\t", i); */
8860 pextra = extra + strlen(extra);
8861 pextra += sprintf(pextra, "0x%03x\t", i);
8862 for (j = 0; j < 8; j++) {
8863 /* RTW_INFO("%02X ", pEfuseHal->BTEfuseInitMap[i+j]); */
8864 pextra += sprintf(pextra, "%02X ", pEfuseHal->BTEfuseInitMap[i+j]);
8865 }
8866 /* RTW_INFO("\t"); */
8867 pextra += sprintf(pextra, "\t");
8868 for (; j < 16; j++) {
8869 /* RTW_INFO("%02X ", pEfuseHal->BTEfuseInitMap[i+j]); */
8870 pextra += sprintf(pextra, "%02X ", pEfuseHal->BTEfuseInitMap[i+j]);
8871 }
8872 /* RTW_INFO("\n"); */
8873 pextra += sprintf(pextra, "\n");
8874 }
8875 /* RTW_INFO("\n"); */
8876 } else if (strcmp(tmp[0], "btbmap") == 0) {
8877 BTEfuse_PowerSwitch(padapter, 1, _TRUE);
8878
8879 mapLen = EFUSE_BT_MAX_MAP_LEN;
8880 if (rtw_BT_efuse_map_read(padapter, 0, mapLen, pEfuseHal->BTEfuseInitMap) == _FAIL) {
8881 RTW_INFO("%s: rtw_BT_efuse_map_read Fail!!\n", __FUNCTION__);
8882 err = -EFAULT;
8883 goto exit;
8884 }
8885
8886 /* RTW_INFO("OFFSET\tVALUE(hex)\n"); */
8887 sprintf(extra, "\n");
8888 for (i = 512; i < 1024 ; i += 16) {
8889 /* RTW_INFO("0x%03x\t", i); */
8890 pextra = extra + strlen(extra);
8891 pextra += sprintf(pextra, "0x%03x\t", i);
8892 for (j = 0; j < 8; j++) {
8893 /* RTW_INFO("%02X ", data[i+j]); */
8894 pextra += sprintf(pextra, "%02X ", pEfuseHal->BTEfuseInitMap[i+j]);
8895 }
8896 /* RTW_INFO("\t"); */
8897 pextra += sprintf(pextra, "\t");
8898 for (; j < 16; j++) {
8899 /* RTW_INFO("%02X ", data[i+j]); */
8900 pextra += sprintf(pextra, "%02X ", pEfuseHal->BTEfuseInitMap[i+j]);
8901 }
8902 /* RTW_INFO("\n"); */
8903 pextra += sprintf(pextra, "\n");
8904 }
8905 /* RTW_INFO("\n"); */
8906 } else if (strcmp(tmp[0], "btrmap") == 0) {
8907 u8 BTStatus;
8908
8909 rtw_write8(padapter, 0xa3, 0x05); /* For 8723AB ,8821S ? */
8910 BTStatus = rtw_read8(padapter, 0xa0);
8911
8912 RTW_INFO("%s: Check 0xa0 BT Status =0x%x\n", __FUNCTION__, BTStatus);
8913 if (BTStatus != 0x04) {
8914 sprintf(extra, "BT Status not Active ,can't to read BT eFuse\n");
8915 goto exit;
8916 }
8917
8918 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
8919 err = -EINVAL;
8920 goto exit;
8921 }
8922
8923 BTEfuse_PowerSwitch(padapter, 1, _TRUE);
8924
8925 /* rmap addr cnts */
8926 addr = simple_strtoul(tmp[1], &ptmp, 16);
8927 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
8928
8929 cnts = simple_strtoul(tmp[2], &ptmp, 10);
8930 if (cnts == 0) {
8931 RTW_INFO("%s: btrmap Fail!! cnts error!\n", __FUNCTION__);
8932 err = -EINVAL;
8933 goto exit;
8934 }
8935 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
8936 #ifndef RTW_HALMAC
8937 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&max_available_len, _FALSE);
8938 if ((addr + cnts) > max_available_len) {
8939 RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
8940 err = -EFAULT;
8941 goto exit;
8942 }
8943 #endif
8944 if (rtw_BT_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
8945 RTW_INFO("%s: rtw_BT_efuse_map_read error!!\n", __FUNCTION__);
8946 err = -EFAULT;
8947 goto exit;
8948 }
8949
8950 *extra = 0;
8951 pextra = extra;
8952 /* RTW_INFO("%s: bt efuse data={", __FUNCTION__); */
8953 for (i = 0; i < cnts; i++) {
8954 /* RTW_INFO("0x%02x ", data[i]); */
8955 pextra += sprintf(pextra, " 0x%02X ", data[i]);
8956 }
8957 /* RTW_INFO("}\n"); */
8958 RTW_INFO(FUNC_ADPT_FMT ": BT MAC=[%s]\n", FUNC_ADPT_ARG(padapter), extra);
8959 } else if (strcmp(tmp[0], "btffake") == 0) {
8960 /* RTW_INFO("OFFSET\tVALUE(hex)\n"); */
8961 sprintf(extra, "\n");
8962 for (i = 0; i < 512; i += 16) {
8963 /* RTW_INFO("0x%03x\t", i); */
8964 pextra = extra + strlen(extra);
8965 pextra += sprintf(pextra, "0x%03x\t", i);
8966 for (j = 0; j < 8; j++) {
8967 /* RTW_INFO("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]); */
8968 pextra += sprintf(pextra, "%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
8969 }
8970 /* RTW_INFO("\t"); */
8971 pextra += sprintf(pextra, "\t");
8972 for (; j < 16; j++) {
8973 /* RTW_INFO("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]); */
8974 pextra += sprintf(pextra, "%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
8975 }
8976 /* RTW_INFO("\n"); */
8977 pextra += sprintf(pextra, "\n");
8978 }
8979 /* RTW_INFO("\n"); */
8980 } else if (strcmp(tmp[0], "btbfake") == 0) {
8981 /* RTW_INFO("OFFSET\tVALUE(hex)\n"); */
8982 sprintf(extra, "\n");
8983 for (i = 512; i < 1024; i += 16) {
8984 /* RTW_INFO("0x%03x\t", i); */
8985 pextra = extra + strlen(extra);
8986 pextra += sprintf(pextra, "0x%03x\t", i);
8987 for (j = 0; j < 8; j++) {
8988 /* RTW_INFO("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]); */
8989 pextra += sprintf(pextra, "%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
8990 }
8991 /* RTW_INFO("\t"); */
8992 pextra += sprintf(pextra, "\t");
8993 for (; j < 16; j++) {
8994 /* RTW_INFO("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]); */
8995 pextra += sprintf(pextra, "%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
8996 }
8997 /* RTW_INFO("\n"); */
8998 pextra += sprintf(pextra, "\n");
8999 }
9000 /* RTW_INFO("\n"); */
9001 } else if (strcmp(tmp[0], "wlrfkmap") == 0) {
9002 static u8 fk_order = 0;
9003 u8 *efuse;
9004 u32 shift, cnt;
9005 u32 blksz = 0x200; /* The size of one time show, default 512 */
9006
9007 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN , (void *)&mapLen, _FALSE);
9008 efuse = pEfuseHal->fakeEfuseModifiedMap;
9009
9010 shift = blksz * fk_order;
9011 efuse += shift;
9012 cnt = mapLen - shift;
9013 if (cnt > blksz) {
9014 cnt = blksz;
9015 fk_order++;
9016 } else
9017 fk_order = 0;
9018
9019 sprintf(extra, "\n");
9020 for (i = 0; i < cnt; i += 16) {
9021 pextra = extra + strlen(extra);
9022 pextra += sprintf(pextra, "0x%02x\t", shift + i);
9023 for (j = 0; j < 8; j++)
9024 pextra += sprintf(pextra, "%02X ", efuse[i + j]);
9025 pextra += sprintf(pextra, "\t");
9026 for (; j < 16; j++)
9027 pextra += sprintf(pextra, "%02X ", efuse[i + j]);
9028 pextra += sprintf(pextra, "\n");
9029 }
9030 if ((shift + cnt) < mapLen)
9031 pextra += sprintf(pextra, "\t...more\n");
9032
9033 } else if (strcmp(tmp[0], "wlrfkrmap") == 0) {
9034 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
9035 RTW_INFO("%s: rmap Fail!! Parameters error!\n", __FUNCTION__);
9036 err = -EINVAL;
9037 goto exit;
9038 }
9039 /* rmap addr cnts */
9040 addr = simple_strtoul(tmp[1], &ptmp, 16);
9041 RTW_INFO("%s: addr=%x\n", __FUNCTION__, addr);
9042
9043 cnts = simple_strtoul(tmp[2], &ptmp, 10);
9044 if (cnts == 0) {
9045 RTW_INFO("%s: rmap Fail!! cnts error!\n", __FUNCTION__);
9046 err = -EINVAL;
9047 goto exit;
9048 }
9049 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9050
9051 /* RTW_INFO("%s: data={", __FUNCTION__); */
9052 *extra = 0;
9053 pextra = extra;
9054 for (i = 0; i < cnts; i++) {
9055 RTW_INFO("wlrfkrmap = 0x%02x\n", pEfuseHal->fakeEfuseModifiedMap[addr + i]);
9056 pextra += sprintf(pextra, "0x%02X ", pEfuseHal->fakeEfuseModifiedMap[addr+i]);
9057 }
9058 } else if (strcmp(tmp[0], "btrfkrmap") == 0) {
9059 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
9060 RTW_INFO("%s: rmap Fail!! Parameters error!\n", __FUNCTION__);
9061 err = -EINVAL;
9062 goto exit;
9063 }
9064 /* rmap addr cnts */
9065 addr = simple_strtoul(tmp[1], &ptmp, 16);
9066 RTW_INFO("%s: addr=%x\n", __FUNCTION__, addr);
9067
9068 cnts = simple_strtoul(tmp[2], &ptmp, 10);
9069 if (cnts == 0) {
9070 RTW_INFO("%s: rmap Fail!! cnts error!\n", __FUNCTION__);
9071 err = -EINVAL;
9072 goto exit;
9073 }
9074 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9075
9076 /* RTW_INFO("%s: data={", __FUNCTION__); */
9077 *extra = 0;
9078 pextra = extra;
9079 for (i = 0; i < cnts; i++) {
9080 RTW_INFO("wlrfkrmap = 0x%02x\n", pEfuseHal->fakeBTEfuseModifiedMap[addr + i]);
9081 pextra += sprintf(pextra, "0x%02X ", pEfuseHal->fakeBTEfuseModifiedMap[addr+i]);
9082 }
9083 } else if (strcmp(tmp[0], "mask") == 0) {
9084 *extra = 0;
9085 mask_len = sizeof(u8) * rtw_get_efuse_mask_arraylen(padapter);
9086 rtw_efuse_mask_array(padapter, mask_buf);
9087
9088 if (padapter->registrypriv.bFileMaskEfuse == _TRUE)
9089 _rtw_memcpy(mask_buf, maskfileBuffer, mask_len);
9090
9091 sprintf(extra, "\n");
9092 pextra = extra + strlen(extra);
9093 for (i = 0; i < mask_len; i++)
9094 pextra += sprintf(pextra, "0x%02X\n", mask_buf[i]);
9095
9096 } else if (strcmp(tmp[0], "btmask") == 0) {
9097 *extra = 0;
9098 mask_len = sizeof(u8) * rtw_get_bt_efuse_mask_arraylen(padapter);
9099 rtw_bt_efuse_mask_array(padapter, mask_buf);
9100
9101 if (padapter->registrypriv.bBTFileMaskEfuse == _TRUE)
9102 _rtw_memcpy(mask_buf, btmaskfileBuffer, mask_len);
9103
9104 sprintf(extra, "\n");
9105 pextra = extra + strlen(extra);
9106 for (i = 0; i < mask_len; i++)
9107 pextra += sprintf(pextra, "0x%02X\n", mask_buf[i]);
9108
9109 } else
9110 sprintf(extra, "Command not found!");
9111
9112 exit:
9113 if (data)
9114 rtw_mfree(data, EFUSE_BT_MAX_MAP_LEN);
9115 if (rawdata)
9116 rtw_mfree(rawdata, EFUSE_BT_MAX_MAP_LEN);
9117 if (!err)
9118 wrqu->length = strlen(extra);
9119
9120 if (padapter->registrypriv.mp_mode == 0) {
9121 #ifdef CONFIG_IPS
9122 rtw_pm_set_ips(padapter, ips_mode);
9123 #endif /* CONFIG_IPS */
9124
9125 #ifdef CONFIG_LPS
9126 rtw_pm_set_lps(padapter, lps_mode);
9127 #endif /* CONFIG_LPS */
9128 }
9129
9130 #ifdef CONFIG_IOL
9131 padapter->registrypriv.fw_iol = org_fw_iol;/* 0:Disable, 1:enable, 2:by usb speed */
9132 #endif
9133 return err;
9134 }
9135
9136
9137 #ifdef CONFIG_MP_INCLUDED
9138 static int rtw_mp_efuse_set(struct net_device *dev,
9139 struct iw_request_info *info,
9140 union iwreq_data *wdata, char *extra)
9141 {
9142 struct iw_point *wrqu;
9143 PADAPTER padapter;
9144 struct pwrctrl_priv *pwrctrlpriv ;
9145 PHAL_DATA_TYPE pHalData;
9146 PEFUSE_HAL pEfuseHal;
9147 struct hal_ops *pHalFunc;
9148 struct mp_priv *pmp_priv;
9149
9150 u8 ips_mode = IPS_NUM; /* init invalid value */
9151 u8 lps_mode = PS_MODE_NUM; /* init invalid value */
9152 u32 i = 0, j = 0, jj, kk;
9153 u8 *setdata = NULL;
9154 u8 *ShadowMapBT = NULL;
9155 u8 *ShadowMapWiFi = NULL;
9156 u8 *setrawdata = NULL;
9157 char *pch, *ptmp, *token, *tmp[3] = {0x00, 0x00, 0x00};
9158 u16 addr = 0xFF, cnts = 0, BTStatus = 0 , max_available_len = 0;
9159 u16 wifimaplen;
9160 int err;
9161 boolean bcmpchk = _TRUE;
9162
9163
9164 wrqu = (struct iw_point *)wdata;
9165 padapter = rtw_netdev_priv(dev);
9166 pwrctrlpriv = adapter_to_pwrctl(padapter);
9167 pHalData = GET_HAL_DATA(padapter);
9168 pEfuseHal = &pHalData->EfuseHal;
9169 pHalFunc = &padapter->hal_func;
9170 pmp_priv = &padapter->mppriv;
9171
9172 err = 0;
9173
9174 if (copy_from_user(extra, wrqu->pointer, wrqu->length))
9175 return -EFAULT;
9176 #ifdef CONFIG_RTL8822C
9177 rtw_pre_bt_efuse(padapter);
9178 #endif
9179 *(extra + wrqu->length) = '\0';
9180
9181 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN , (void *)&wifimaplen, _FALSE);
9182
9183 setdata = rtw_zmalloc(1024);
9184 if (setdata == NULL) {
9185 err = -ENOMEM;
9186 goto exit;
9187 }
9188 ShadowMapBT = rtw_malloc(EFUSE_BT_MAX_MAP_LEN);
9189 if (ShadowMapBT == NULL) {
9190 err = -ENOMEM;
9191 goto exit;
9192 }
9193 ShadowMapWiFi = rtw_malloc(wifimaplen);
9194 if (ShadowMapWiFi == NULL) {
9195 err = -ENOMEM;
9196 goto exit;
9197 }
9198 setrawdata = rtw_malloc(EFUSE_MAX_SIZE);
9199 if (setrawdata == NULL) {
9200 err = -ENOMEM;
9201 goto exit;
9202 }
9203
9204 #ifdef CONFIG_LPS
9205 lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */
9206 rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
9207 #endif
9208
9209 #ifdef CONFIG_IPS
9210 ips_mode = pwrctrlpriv->ips_mode;/* keep org value */
9211 rtw_pm_set_ips(padapter, IPS_NONE);
9212 #endif
9213
9214 pch = extra;
9215 RTW_INFO("%s: in=%s\n", __FUNCTION__, extra);
9216
9217 i = 0;
9218 while ((token = strsep(&pch, ",")) != NULL) {
9219 if (i > 2)
9220 break;
9221 tmp[i] = token;
9222 i++;
9223 }
9224
9225 /* tmp[0],[1],[2] */
9226 /* wmap,addr,00e04c871200 */
9227 if (strcmp(tmp[0], "wmap") == 0) {
9228 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
9229 err = -EINVAL;
9230 goto exit;
9231 }
9232
9233 #ifndef RTW_HALMAC
9234 /* unknown bug workaround, need to fix later */
9235 addr = 0x1ff;
9236 rtw_write8(padapter, EFUSE_CTRL + 1, (addr & 0xff));
9237 rtw_msleep_os(10);
9238 rtw_write8(padapter, EFUSE_CTRL + 2, ((addr >> 8) & 0x03));
9239 rtw_msleep_os(10);
9240 rtw_write8(padapter, EFUSE_CTRL + 3, 0x72);
9241 rtw_msleep_os(10);
9242 rtw_read8(padapter, EFUSE_CTRL);
9243 #endif /* RTW_HALMAC */
9244
9245 addr = simple_strtoul(tmp[1], &ptmp, 16);
9246 addr &= 0xFFF;
9247
9248 cnts = strlen(tmp[2]);
9249 if (cnts % 2) {
9250 err = -EINVAL;
9251 goto exit;
9252 }
9253 cnts /= 2;
9254 if (cnts == 0) {
9255 err = -EINVAL;
9256 goto exit;
9257 }
9258
9259 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
9260 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9261 RTW_INFO("%s: map data=%s\n", __FUNCTION__, tmp[2]);
9262
9263 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
9264 setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
9265
9266 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_len, _FALSE);
9267
9268 if ((addr + cnts) > max_available_len) {
9269 RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
9270 err = -EFAULT;
9271 goto exit;
9272 }
9273
9274 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
9275 RTW_INFO("%s: rtw_efuse_map_write error!!\n", __FUNCTION__);
9276 err = -EFAULT;
9277 goto exit;
9278 }
9279 *extra = 0;
9280 RTW_INFO("%s: after rtw_efuse_map_write to _rtw_memcmp\n", __func__);
9281 if (rtw_efuse_mask_map_read(padapter, addr, cnts, ShadowMapWiFi) == _SUCCESS) {
9282 if (_rtw_memcmp((void *)ShadowMapWiFi , (void *)setdata, cnts)) {
9283 RTW_INFO("%s: WiFi write map afterf compare success\n", __FUNCTION__);
9284 sprintf(extra, "WiFi write map compare OK\n");
9285 err = 0;
9286 goto exit;
9287 } else {
9288 sprintf(extra, "WiFi write map compare FAIL\n");
9289 RTW_INFO("%s: WiFi write map compare Fail\n", __FUNCTION__);
9290 err = 0;
9291 goto exit;
9292 }
9293 }
9294 } else if (strcmp(tmp[0], "wraw") == 0) {
9295 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
9296 err = -EINVAL;
9297 goto exit;
9298 }
9299
9300 addr = simple_strtoul(tmp[1], &ptmp, 16);
9301 addr &= 0xFFF;
9302
9303 cnts = strlen(tmp[2]);
9304 if (cnts % 2) {
9305 err = -EINVAL;
9306 goto exit;
9307 }
9308 cnts /= 2;
9309 if (cnts == 0) {
9310 err = -EINVAL;
9311 goto exit;
9312 }
9313
9314 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
9315 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9316 RTW_INFO("%s: raw data=%s\n", __FUNCTION__, tmp[2]);
9317
9318 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
9319 setrawdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
9320
9321 if (rtw_efuse_access(padapter, _TRUE, addr, cnts, setrawdata) == _FAIL) {
9322 RTW_INFO("%s: rtw_efuse_access error!!\n", __FUNCTION__);
9323 err = -EFAULT;
9324 goto exit;
9325 }
9326 } else if (strcmp(tmp[0], "btwraw") == 0) {
9327 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
9328 err = -EINVAL;
9329 goto exit;
9330 }
9331
9332 addr = simple_strtoul(tmp[1], &ptmp, 16);
9333 addr &= 0xFFF;
9334
9335 cnts = strlen(tmp[2]);
9336 if (cnts % 2) {
9337 err = -EINVAL;
9338 goto exit;
9339 }
9340 cnts /= 2;
9341 if (cnts == 0) {
9342 err = -EINVAL;
9343 goto exit;
9344 }
9345
9346 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
9347 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9348 RTW_INFO("%s: raw data=%s\n", __FUNCTION__, tmp[2]);
9349
9350 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
9351 setrawdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
9352 #ifdef RTW_HALMAC
9353 if (rtw_efuse_bt_access(padapter, _TRUE, addr, cnts, setrawdata) == _FAIL) {
9354 RTW_INFO("%s: rtw_efuse_access error!!\n", __FUNCTION__);
9355 err = -EFAULT;
9356 goto exit;
9357 }
9358 #else
9359 rtw_write8(padapter, 0x35, 1); /* switch bank 1 (BT)*/
9360 if (rtw_efuse_access(padapter, _TRUE, addr, cnts, setrawdata) == _FAIL) {
9361 RTW_INFO("%s: rtw_efuse_access error!!\n", __FUNCTION__);
9362 rtw_write8(padapter, 0x35, 0); /* switch bank 0 (WiFi)*/
9363 err = -EFAULT;
9364 goto exit;
9365 }
9366 rtw_write8(padapter, 0x35, 0); /* switch bank 0 (WiFi)*/
9367 #endif
9368 } else if (strcmp(tmp[0], "mac") == 0) {
9369 if (tmp[1] == NULL) {
9370 err = -EINVAL;
9371 goto exit;
9372 }
9373
9374 /* mac,00e04c871200 */
9375
9376 if (hal_efuse_macaddr_offset(padapter) == -1) {
9377 err = -EFAULT;
9378 goto exit;
9379 }
9380
9381 addr = hal_efuse_macaddr_offset(padapter);
9382 cnts = strlen(tmp[1]);
9383 if (cnts % 2) {
9384 err = -EINVAL;
9385 goto exit;
9386 }
9387 cnts /= 2;
9388 if (cnts == 0) {
9389 err = -EINVAL;
9390 goto exit;
9391 }
9392 if (cnts > 6) {
9393 RTW_INFO("%s: error data for mac addr=\"%s\"\n", __FUNCTION__, tmp[1]);
9394 err = -EFAULT;
9395 goto exit;
9396 }
9397
9398 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
9399 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9400 RTW_INFO("%s: MAC address=%s\n", __FUNCTION__, tmp[1]);
9401
9402 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
9403 setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
9404
9405 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_len, _FALSE);
9406
9407 if ((addr + cnts) > max_available_len) {
9408 RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
9409 err = -EFAULT;
9410 goto exit;
9411 }
9412
9413 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
9414 RTW_INFO("%s: rtw_efuse_map_write error!!\n", __FUNCTION__);
9415 err = -EFAULT;
9416 goto exit;
9417 }
9418 } else if (strcmp(tmp[0], "vidpid") == 0) {
9419 if (tmp[1] == NULL) {
9420 err = -EINVAL;
9421 goto exit;
9422 }
9423
9424 /* pidvid,da0b7881 */
9425 #ifdef CONFIG_RTL8188E
9426 #ifdef CONFIG_USB_HCI
9427 addr = EEPROM_VID_88EU;
9428 #endif
9429 #ifdef CONFIG_PCI_HCI
9430 addr = EEPROM_VID_88EE;
9431 #endif
9432 #endif /* CONFIG_RTL8188E */
9433
9434 #ifdef CONFIG_RTL8192E
9435 #ifdef CONFIG_USB_HCI
9436 addr = EEPROM_VID_8192EU;
9437 #endif
9438 #ifdef CONFIG_PCI_HCI
9439 addr = EEPROM_VID_8192EE;
9440 #endif
9441 #endif /* CONFIG_RTL8188E */
9442
9443 #ifdef CONFIG_RTL8723B
9444 addr = EEPROM_VID_8723BU;
9445 #endif
9446
9447 #ifdef CONFIG_RTL8188F
9448 addr = EEPROM_VID_8188FU;
9449 #endif
9450
9451 #ifdef CONFIG_RTL8188GTV
9452 addr = EEPROM_VID_8188GTVU;
9453 #endif
9454
9455 #ifdef CONFIG_RTL8703B
9456 #ifdef CONFIG_USB_HCI
9457 addr = EEPROM_VID_8703BU;
9458 #endif /* CONFIG_USB_HCI */
9459 #endif /* CONFIG_RTL8703B */
9460
9461 #ifdef CONFIG_RTL8723D
9462 #ifdef CONFIG_USB_HCI
9463 addr = EEPROM_VID_8723DU;
9464 #endif /* CONFIG_USB_HCI */
9465 #endif /* CONFIG_RTL8723D */
9466
9467 cnts = strlen(tmp[1]);
9468 if (cnts % 2) {
9469 err = -EINVAL;
9470 goto exit;
9471 }
9472 cnts /= 2;
9473 if (cnts == 0) {
9474 err = -EINVAL;
9475 goto exit;
9476 }
9477
9478 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
9479 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9480 RTW_INFO("%s: VID/PID=%s\n", __FUNCTION__, tmp[1]);
9481
9482 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
9483 setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
9484
9485 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_len, _FALSE);
9486 if ((addr + cnts) > max_available_len) {
9487 RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
9488 err = -EFAULT;
9489 goto exit;
9490 }
9491
9492 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
9493 RTW_INFO("%s: rtw_efuse_map_write error!!\n", __FUNCTION__);
9494 err = -EFAULT;
9495 goto exit;
9496 }
9497 } else if (strcmp(tmp[0], "wldumpfake") == 0) {
9498 if (wifimaplen > EFUSE_MAX_MAP_LEN)
9499 cnts = EFUSE_MAX_MAP_LEN;
9500 else
9501 cnts = wifimaplen;
9502 if (rtw_efuse_mask_map_read(padapter, 0, cnts, pEfuseHal->fakeEfuseModifiedMap) == _SUCCESS)
9503 RTW_INFO("%s: WiFi hw efuse dump to Fake map success\n", __func__);
9504 else {
9505 RTW_INFO("%s: WiFi hw efuse dump to Fake map Fail\n", __func__);
9506 err = -EFAULT;
9507 }
9508 } else if (strcmp(tmp[0], "btwmap") == 0) {
9509 rtw_write8(padapter, 0xa3, 0x05); /* For 8723AB ,8821S ? */
9510 BTStatus = rtw_read8(padapter, 0xa0);
9511 RTW_INFO("%s: btwmap before read 0xa0 BT Status =0x%x\n", __FUNCTION__, BTStatus);
9512 if (BTStatus != 0x04) {
9513 sprintf(extra, "BT Status not Active ,can't do Write\n");
9514 goto exit;
9515 }
9516
9517 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
9518 err = -EINVAL;
9519 goto exit;
9520 }
9521
9522 #ifndef RTW_HALMAC
9523 BTEfuse_PowerSwitch(padapter, 1, _TRUE);
9524 addr = 0x1ff;
9525 rtw_write8(padapter, EFUSE_CTRL + 1, (addr & 0xff));
9526 rtw_msleep_os(10);
9527 rtw_write8(padapter, EFUSE_CTRL + 2, ((addr >> 8) & 0x03));
9528 rtw_msleep_os(10);
9529 rtw_write8(padapter, EFUSE_CTRL + 3, 0x72);
9530 rtw_msleep_os(10);
9531 rtw_read8(padapter, EFUSE_CTRL);
9532 BTEfuse_PowerSwitch(padapter, 1, _FALSE);
9533 #endif /* RTW_HALMAC */
9534
9535 addr = simple_strtoul(tmp[1], &ptmp, 16);
9536 addr &= 0xFFF;
9537
9538 cnts = strlen(tmp[2]);
9539 if (cnts % 2) {
9540 err = -EINVAL;
9541 goto exit;
9542 }
9543 cnts /= 2;
9544 if (cnts == 0) {
9545 err = -EINVAL;
9546 goto exit;
9547 }
9548
9549 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
9550 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9551 RTW_INFO("%s: BT data=%s\n", __FUNCTION__, tmp[2]);
9552
9553 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
9554 setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
9555 #ifndef RTW_HALMAC
9556 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&max_available_len, _FALSE);
9557 if ((addr + cnts) > max_available_len) {
9558 RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
9559 err = -EFAULT;
9560 goto exit;
9561 }
9562 #endif
9563 if (rtw_BT_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
9564 RTW_INFO("%s: rtw_BT_efuse_map_write error!!\n", __FUNCTION__);
9565 sprintf(extra, "BT write FAIL !!!\n");
9566 err = -EFAULT;
9567 goto exit;
9568 }
9569 *extra = 0;
9570 RTW_INFO("%s: after rtw_BT_efuse_map_write to _rtw_memcmp\n", __FUNCTION__);
9571 if ((rtw_BT_efuse_map_read(padapter, addr, cnts, ShadowMapBT) == _SUCCESS)) {
9572 if (_rtw_memcmp((void *)ShadowMapBT , (void *)setdata, cnts)) {
9573 RTW_INFO("%s: BT write map compare OK BTStatus=0x%x\n", __FUNCTION__, BTStatus);
9574 sprintf(extra, "BT write map compare OK");
9575 err = 0;
9576 goto exit;
9577 } else {
9578 sprintf(extra, "BT write map compare FAIL");
9579 RTW_INFO("%s: BT write map compare FAIL BTStatus=0x%x\n", __FUNCTION__, BTStatus);
9580 err = 0;
9581 goto exit;
9582 }
9583 }
9584 } else if (strcmp(tmp[0], "btwfake") == 0) {
9585 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
9586 err = -EINVAL;
9587 goto exit;
9588 }
9589 if (pmp_priv->bprocess_mp_mode != _TRUE) {
9590 RTW_INFO("%s: btwfake not to be exec, please first to mp_start\n", __FUNCTION__);
9591 sprintf(extra, "Error, btwfake cant to be exec, please first to mp_start !!!!\n");
9592 err = 0;
9593 goto exit;
9594 }
9595 addr = simple_strtoul(tmp[1], &ptmp, 16);
9596 addr &= 0xFFF;
9597
9598 cnts = strlen(tmp[2]);
9599 if (cnts % 2) {
9600 err = -EINVAL;
9601 goto exit;
9602 }
9603 cnts /= 2;
9604 if (cnts == 0) {
9605 err = -EINVAL;
9606 goto exit;
9607 }
9608
9609 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
9610 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9611 RTW_INFO("%s: BT tmp data=%s\n", __FUNCTION__, tmp[2]);
9612
9613 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
9614 pEfuseHal->fakeBTEfuseModifiedMap[addr + jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
9615 } else if (strcmp(tmp[0], "btdumpfake") == 0) {
9616 if (rtw_BT_efuse_map_read(padapter, 0, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _SUCCESS)
9617 RTW_INFO("%s: BT read all map success\n", __FUNCTION__);
9618 else {
9619 RTW_INFO("%s: BT read all map Fail!\n", __FUNCTION__);
9620 err = -EFAULT;
9621 }
9622 } else if (strcmp(tmp[0], "btfk2map") == 0) {
9623 #ifdef CONFIG_BT_EFUSE_MASK
9624 if (padapter->registrypriv.bBTFileMaskEfuse != _TRUE && pmp_priv->bloadBTefusemap == _TRUE) {
9625 RTW_INFO("%s: File BT eFuse mask file not to be loaded\n", __FUNCTION__);
9626 sprintf(extra, "Not load BT eFuse mask file yet, Please advance to use [ efuse_bt_mask ], now remove the Adapter.!!!!\n");
9627 rtw_set_surprise_removed(padapter);
9628 err = 0;
9629 goto exit;
9630 }
9631 #endif
9632 rtw_write8(padapter, 0xa3, 0x05);
9633 BTStatus = rtw_read8(padapter, 0xa0);
9634 RTW_INFO("%s: btwmap before read 0xa0 BT Status =0x%x\n", __FUNCTION__, BTStatus);
9635 if (BTStatus != 0x04) {
9636 sprintf(extra, "BT Status not Active Write FAIL\n");
9637 goto exit;
9638 }
9639 if (pmp_priv->bprocess_mp_mode != _TRUE) {
9640 RTW_INFO("%s: btfk2map not to be exec, please first to mp_start\n", __FUNCTION__);
9641 sprintf(extra, "Error, btfk2map cant to be exec, please first to mp_start !!!!\n");
9642 err = 0;
9643 goto exit;
9644 }
9645 #ifndef RTW_HALMAC
9646 BTEfuse_PowerSwitch(padapter, 1, _TRUE);
9647 addr = 0x1ff;
9648 rtw_write8(padapter, EFUSE_CTRL + 1, (addr & 0xff));
9649 rtw_msleep_os(10);
9650 rtw_write8(padapter, EFUSE_CTRL + 2, ((addr >> 8) & 0x03));
9651 rtw_msleep_os(10);
9652 rtw_write8(padapter, EFUSE_CTRL + 3, 0x72);
9653 rtw_msleep_os(10);
9654 rtw_read8(padapter, EFUSE_CTRL);
9655 BTEfuse_PowerSwitch(padapter, 1, _FALSE);
9656 #endif /* RTW_HALMAC */
9657
9658 if (rtw_BT_efuse_map_write(padapter, 0x00, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _FAIL) {
9659 RTW_INFO("%s: rtw_BT_efuse_map_write error!\n", __FUNCTION__);
9660 sprintf(extra, "BT write FAIL !!!\n");
9661 err = -EFAULT;
9662 goto exit;
9663 }
9664
9665 RTW_INFO("pEfuseHal->fakeBTEfuseModifiedMap OFFSET\tVALUE(hex)\n");
9666 for (i = 0; i < EFUSE_BT_MAX_MAP_LEN; i += 16) {
9667 printk("0x%02x\t", i);
9668 for (j = 0; j < 8; j++)
9669 printk("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
9670 printk("\t");
9671
9672 for (; j < 16; j++)
9673 printk("%02X ", pEfuseHal->fakeBTEfuseModifiedMap[i + j]);
9674 printk("\n");
9675 }
9676 printk("\n");
9677 #if 1
9678 err = -EFAULT;
9679 RTW_INFO("%s: rtw_BT_efuse_map_read _rtw_memcmp\n", __FUNCTION__);
9680 if ((rtw_BT_efuse_map_read(padapter, 0x00, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseInitMap) == _SUCCESS)) {
9681 if (_rtw_memcmp((void *)pEfuseHal->fakeBTEfuseModifiedMap, (void *)pEfuseHal->fakeBTEfuseInitMap, EFUSE_BT_MAX_MAP_LEN)) {
9682 sprintf(extra, "BT write map compare OK");
9683 RTW_INFO("%s: BT write map afterf compare success BTStatus=0x%x\n", __FUNCTION__, BTStatus);
9684 err = 0;
9685 goto exit;
9686 } else {
9687 sprintf(extra, "BT write map compare FAIL");
9688 if (rtw_BT_efuse_map_write(padapter, 0x00, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseModifiedMap) == _FAIL)
9689 RTW_INFO("%s: rtw_BT_efuse_map_write compare error,retry = %d!\n", __FUNCTION__, i);
9690
9691 if (rtw_BT_efuse_map_read(padapter, EFUSE_BT, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeBTEfuseInitMap) == _SUCCESS) {
9692 RTW_INFO("pEfuseHal->fakeBTEfuseInitMap OFFSET\tVALUE(hex)\n");
9693
9694 for (i = 0; i < EFUSE_BT_MAX_MAP_LEN; i += 16) {
9695 printk("0x%02x\t", i);
9696 for (j = 0; j < 8; j++)
9697 printk("%02X ", pEfuseHal->fakeBTEfuseInitMap[i + j]);
9698 printk("\t");
9699 for (; j < 16; j++)
9700 printk("%02X ", pEfuseHal->fakeBTEfuseInitMap[i + j]);
9701 printk("\n");
9702 }
9703 printk("\n");
9704 }
9705 RTW_INFO("%s: BT write map afterf compare not match to write efuse try write Map again , BTStatus=0x%x\n", __FUNCTION__, BTStatus);
9706 goto exit;
9707 }
9708 }
9709 #endif
9710
9711 } else if (strcmp(tmp[0], "wlfk2map") == 0) {
9712 *extra = 0;
9713
9714 if (padapter->registrypriv.bFileMaskEfuse != _TRUE && pmp_priv->bloadefusemap == _TRUE) {
9715 RTW_INFO("%s: File eFuse mask file not to be loaded\n", __FUNCTION__);
9716 sprintf(extra, "Not load eFuse mask file yet, Please use the efuse_mask CMD, now remove the interface !!!!\n");
9717 rtw_set_surprise_removed(padapter);
9718 err = 0;
9719 goto exit;
9720 }
9721
9722 if (pmp_priv->bprocess_mp_mode != _TRUE) {
9723 RTW_INFO("%s: wlfk2map not to be exec, please first to mp_start\n", __FUNCTION__);
9724 sprintf(extra, "Error, wlfk2map cant to be exec, please first to mp_start !!!!\n");
9725 err = 0;
9726 goto exit;
9727 }
9728 if (wifimaplen > EFUSE_MAX_MAP_LEN)
9729 cnts = EFUSE_MAX_MAP_LEN;
9730 else
9731 cnts = wifimaplen;
9732 if (rtw_efuse_map_write(padapter, 0x00, cnts, pEfuseHal->fakeEfuseModifiedMap) == _FAIL) {
9733 RTW_INFO("%s: rtw_efuse_map_write fakeEfuseModifiedMap error!\n", __FUNCTION__);
9734 err = -EFAULT;
9735 goto exit;
9736 }
9737
9738 if (rtw_efuse_mask_map_read(padapter, 0x00, wifimaplen, ShadowMapWiFi) == _SUCCESS) {
9739 addr = 0x00;
9740 err = _TRUE;
9741
9742 for (i = 0; i < cnts; i++) {
9743 if (padapter->registrypriv.boffefusemask == 0) {
9744 if (padapter->registrypriv.bFileMaskEfuse == _TRUE) {
9745 if (rtw_file_efuse_IsMasked(padapter, addr + i, maskfileBuffer) == _TRUE) /*use file efuse mask. */
9746 bcmpchk = _FALSE;
9747 } else {
9748 if (efuse_IsMasked(padapter, addr + i) == _TRUE)
9749 bcmpchk = _FALSE;
9750 }
9751 }
9752
9753 if (bcmpchk == _TRUE) {
9754 RTW_INFO("compare readMapWiFi[0x%02x] = %x, ModifiedMap = %x\n", addr + i, ShadowMapWiFi[ addr + i], pEfuseHal->fakeEfuseModifiedMap[addr + i]);
9755 if (_rtw_memcmp((void *) &ShadowMapWiFi[addr + i], (void *)&pEfuseHal->fakeEfuseModifiedMap[addr + i], 1) == _FALSE){
9756 err = _FALSE;
9757 break;
9758 }
9759 }
9760 bcmpchk = _TRUE;
9761 }
9762 }
9763
9764 if (err) {
9765 RTW_INFO("%s: WiFi write map afterf compare OK\n", __FUNCTION__);
9766 sprintf(extra, "WiFi write map compare OK\n");
9767 err = 0;
9768 goto exit;
9769 } else {
9770 sprintf(extra, "WiFi write map compare FAIL\n");
9771 RTW_INFO("%s: WiFi write map compare Fail\n", __FUNCTION__);
9772 err = 0;
9773 goto exit;
9774 }
9775 } else if (strcmp(tmp[0], "wlwfake") == 0) {
9776 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
9777 err = -EINVAL;
9778 goto exit;
9779 }
9780 if (pmp_priv->bprocess_mp_mode != _TRUE) {
9781 RTW_INFO("%s: wlwfake not to be exec, please first to mp_start\n", __FUNCTION__);
9782 sprintf(extra, "Error, wlwfake cant to be exec, please first to mp_start !!!!\n");
9783 err = 0;
9784 goto exit;
9785 }
9786 addr = simple_strtoul(tmp[1], &ptmp, 16);
9787 addr &= 0xFFF;
9788
9789 cnts = strlen(tmp[2]);
9790 if (cnts % 2) {
9791 err = -EINVAL;
9792 goto exit;
9793 }
9794 cnts /= 2;
9795 if (cnts == 0) {
9796 err = -EINVAL;
9797 goto exit;
9798 }
9799
9800 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
9801 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9802 RTW_INFO("%s: map tmp data=%s\n", __FUNCTION__, tmp[2]);
9803
9804 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
9805 pEfuseHal->fakeEfuseModifiedMap[addr + jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
9806 _rtw_memset(extra, '\0', strlen(extra));
9807 sprintf(extra, "wlwfake OK\n");
9808
9809 }
9810 else if (strcmp(tmp[0], "wfakemac") == 0) {
9811 if (tmp[1] == NULL) {
9812 err = -EINVAL;
9813 goto exit;
9814 }
9815 if (pmp_priv->bprocess_mp_mode != _TRUE) {
9816 RTW_INFO("%s: wfakemac not to be exec, please first to mp_start\n", __FUNCTION__);
9817 sprintf(extra, "Error, wfakemac cant to be exec, please first to mp_start !!!!\n");
9818 err = 0;
9819 goto exit;
9820 }
9821 /* wfakemac,00e04c871200 */
9822 if (hal_efuse_macaddr_offset(padapter) == -1) {
9823 err = -EFAULT;
9824 goto exit;
9825 }
9826
9827 addr = hal_efuse_macaddr_offset(padapter);
9828 cnts = strlen(tmp[1]);
9829 if (cnts % 2) {
9830 err = -EINVAL;
9831 goto exit;
9832 }
9833 cnts /= 2;
9834 if (cnts == 0) {
9835 err = -EINVAL;
9836 goto exit;
9837 }
9838 if (cnts > 6) {
9839 RTW_INFO("%s: error data for mac addr=\"%s\"\n", __FUNCTION__, tmp[1]);
9840 err = -EFAULT;
9841 goto exit;
9842 }
9843
9844 RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
9845 RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
9846 RTW_INFO("%s: MAC address=%s\n", __FUNCTION__, tmp[1]);
9847
9848 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
9849 if ((addr + jj) < EFUSE_MAX_MAP_LEN)
9850 pEfuseHal->fakeEfuseModifiedMap[addr + jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
9851
9852 _rtw_memset(extra, '\0', strlen(extra));
9853 sprintf(extra, "write mac addr to fake map OK\n");
9854 } else if(strcmp(tmp[0], "update") == 0) {
9855 RTW_INFO("To Use new eFuse map\n");
9856 /*step read efuse/eeprom data and get mac_addr*/
9857 rtw_hal_read_chip_info(padapter);
9858 /* set mac addr*/
9859 rtw_macaddr_cfg(adapter_mac_addr(padapter), get_hal_mac_addr(padapter));
9860 _rtw_memcpy(padapter->pnetdev->dev_addr, get_hal_mac_addr(padapter), ETH_ALEN); /* set mac addr to net_device */
9861
9862 #ifdef CONFIG_P2P
9863 rtw_init_wifidirect_addrs(padapter, adapter_mac_addr(padapter), adapter_mac_addr(padapter));
9864 #endif
9865 #ifdef CONFIG_MI_WITH_MBSSID_CAM
9866 rtw_hal_change_macaddr_mbid(padapter, adapter_mac_addr(padapter));
9867 #else
9868 rtw_hal_set_hwreg(padapter, HW_VAR_MAC_ADDR, adapter_mac_addr(padapter)); /* set mac addr to mac register */
9869 #endif
9870 /*pHalFunc->hal_deinit(padapter);*/
9871 if (pHalFunc->hal_init(padapter) == _FAIL) {
9872 err = -EINVAL;
9873 goto exit;
9874 }
9875 pHalData->current_channel = 0;
9876 pHalData->current_channel_bw = CHANNEL_WIDTH_MAX;
9877 pHalData->current_band_type = BAND_MAX;
9878
9879 _rtw_memset(extra, '\0', strlen(extra));
9880 sprintf(extra, "eFuse Update OK\n");
9881 } else if (strcmp(tmp[0], "analyze") == 0) {
9882
9883 rtw_efuse_analyze(padapter, EFUSE_WIFI, 0);
9884 _rtw_memset(extra, '\0', strlen(extra));
9885 sprintf(extra, "eFuse Analyze OK,please to check kernel log\n");
9886 }
9887 exit:
9888 if (setdata)
9889 rtw_mfree(setdata, 1024);
9890 if (ShadowMapBT)
9891 rtw_mfree(ShadowMapBT, EFUSE_BT_MAX_MAP_LEN);
9892 if (ShadowMapWiFi)
9893 rtw_mfree(ShadowMapWiFi, wifimaplen);
9894 if (setrawdata)
9895 rtw_mfree(setrawdata, EFUSE_MAX_SIZE);
9896
9897 wrqu->length = strlen(extra);
9898
9899 if (padapter->registrypriv.mp_mode == 0) {
9900 #ifdef CONFIG_IPS
9901 rtw_pm_set_ips(padapter, ips_mode);
9902 #endif /* CONFIG_IPS */
9903
9904 #ifdef CONFIG_LPS
9905 rtw_pm_set_lps(padapter, lps_mode);
9906 #endif /* CONFIG_LPS */
9907 }
9908
9909 return err;
9910 }
9911
9912 #ifdef CONFIG_RTW_CUSTOMER_STR
9913 static int rtw_mp_customer_str(
9914 struct net_device *dev,
9915 struct iw_request_info *info,
9916 union iwreq_data *wrqu, char *extra)
9917 {
9918 _adapter *adapter = rtw_netdev_priv(dev);
9919 u32 len;
9920 u8 *pbuf = NULL, *pch;
9921 char *ptmp;
9922 u8 param[RTW_CUSTOMER_STR_LEN];
9923 u8 count = 0;
9924 u8 tmp;
9925 u8 i;
9926 u32 pos;
9927 u8 ret;
9928 u8 read = 0;
9929
9930 if (adapter->registrypriv.mp_mode != 1
9931 || !adapter->registrypriv.mp_customer_str)
9932 return -EFAULT;
9933
9934 len = wrqu->data.length + 1;
9935
9936 pbuf = (u8 *)rtw_zmalloc(len);
9937 if (pbuf == NULL) {
9938 RTW_WARN("%s: no memory!\n", __func__);
9939 return -ENOMEM;
9940 }
9941
9942 if (copy_from_user(pbuf, wrqu->data.pointer, wrqu->data.length)) {
9943 rtw_mfree(pbuf, len);
9944 RTW_WARN("%s: copy from user fail!\n", __func__);
9945 return -EFAULT;
9946 }
9947 RTW_INFO("%s: string=\"%s\"\n", __func__, pbuf);
9948
9949 ptmp = (char *)pbuf;
9950 pch = strsep(&ptmp, ",");
9951 if ((pch == NULL) || (strlen(pch) == 0)) {
9952 rtw_mfree(pbuf, len);
9953 RTW_INFO("%s: parameter error(no cmd)!\n", __func__);
9954 return -EFAULT;
9955 }
9956
9957 _rtw_memset(param, 0xFF, RTW_CUSTOMER_STR_LEN);
9958
9959 if (strcmp(pch, "read") == 0) {
9960 read = 1;
9961 ret = rtw_hal_customer_str_read(adapter, param);
9962
9963 } else if (strcmp(pch, "write") == 0) {
9964 do {
9965 pch = strsep(&ptmp, ":");
9966 if ((pch == NULL) || (strlen(pch) == 0))
9967 break;
9968 if (strlen(pch) != 2
9969 || IsHexDigit(*pch) == _FALSE
9970 || IsHexDigit(*(pch + 1)) == _FALSE
9971 || sscanf(pch, "%hhx", &tmp) != 1
9972 ) {
9973 RTW_WARN("%s: invalid 8-bit hex!\n", __func__);
9974 rtw_mfree(pbuf, len);
9975 return -EFAULT;
9976 }
9977
9978 param[count++] = tmp;
9979
9980 } while (count < RTW_CUSTOMER_STR_LEN);
9981
9982 if (count == 0) {
9983 rtw_mfree(pbuf, len);
9984 RTW_WARN("%s: no input!\n", __func__);
9985 return -EFAULT;
9986 }
9987 ret = rtw_hal_customer_str_write(adapter, param);
9988 } else {
9989 rtw_mfree(pbuf, len);
9990 RTW_INFO("%s: parameter error(unknown cmd)!\n", __func__);
9991 return -EFAULT;
9992 }
9993
9994 pos = sprintf(extra, "%s: ", read ? "read" : "write");
9995 if (read == 0 || ret == _SUCCESS) {
9996 for (i = 0; i < RTW_CUSTOMER_STR_LEN; i++)
9997 pos += sprintf(extra + pos, "%02x:", param[i]);
9998 extra[pos] = 0;
9999 pos--;
10000 }
10001 pos += sprintf(extra + pos, " %s", ret == _SUCCESS ? "OK" : "FAIL");
10002
10003 wrqu->data.length = strlen(extra) + 1;
10004
10005 rtw_mfree(pbuf, len);
10006 return 0;
10007 }
10008 #endif /* CONFIG_RTW_CUSTOMER_STR */
10009
10010 static int rtw_priv_mp_set(struct net_device *dev,
10011 struct iw_request_info *info,
10012 union iwreq_data *wdata, char *extra)
10013 {
10014
10015 struct iw_point *wrqu = (struct iw_point *)wdata;
10016 u32 subcmd = wrqu->flags;
10017 PADAPTER padapter = rtw_netdev_priv(dev);
10018 int status = 0;
10019
10020 #ifdef CONFIG_CONCURRENT_MODE
10021 if (!is_primary_adapter(padapter)) {
10022 RTW_INFO("MP mode only primary Adapter support\n");
10023 return -EIO;
10024 }
10025 #endif
10026
10027 RTW_INFO("%s mutx in %d\n", __func__, subcmd);
10028 _enter_critical_mutex(&(adapter_to_dvobj(padapter)->ioctrl_mutex), NULL);
10029 switch (subcmd) {
10030 case CTA_TEST:
10031 RTW_INFO("set CTA_TEST\n");
10032 status = rtw_cta_test_start(dev, info, wdata, extra);
10033 break;
10034 case MP_DISABLE_BT_COEXIST:
10035 RTW_INFO("set case MP_DISABLE_BT_COEXIST\n");
10036 status = rtw_mp_disable_bt_coexist(dev, info, wdata, extra);
10037 break;
10038 case MP_IQK:
10039 RTW_INFO("set MP_IQK\n");
10040 status = rtw_mp_iqk(dev, info, wrqu, extra);
10041 break;
10042 case MP_LCK:
10043 RTW_INFO("set MP_LCK\n");
10044 status = rtw_mp_lck(dev, info, wrqu, extra);
10045 break;
10046
10047 default:
10048 status = -EIO;
10049 }
10050 _exit_critical_mutex(&(adapter_to_dvobj(padapter)->ioctrl_mutex), NULL);
10051 RTW_INFO("%s mutx done %d\n", __func__, subcmd);
10052
10053 return status;
10054 }
10055
10056 static int rtw_priv_mp_get(struct net_device *dev,
10057 struct iw_request_info *info,
10058 union iwreq_data *wdata, char *extra)
10059 {
10060
10061 struct iw_point *wrqu = (struct iw_point *)wdata;
10062 u32 subcmd = wrqu->flags;
10063 PADAPTER padapter = rtw_netdev_priv(dev);
10064 int status = 0;
10065
10066 #ifdef CONFIG_CONCURRENT_MODE
10067 if (!is_primary_adapter(padapter)) {
10068 RTW_INFO("MP mode only primary Adapter support\n");
10069 return -EIO;
10070 }
10071 #endif
10072
10073 RTW_INFO("%s mutx in %d\n", __func__, subcmd);
10074 _enter_critical_mutex(&(adapter_to_dvobj(padapter)->ioctrl_mutex), NULL);
10075
10076 switch (subcmd) {
10077 case MP_START:
10078 RTW_INFO("set case mp_start\n");
10079 status = rtw_mp_start(dev, info, wrqu, extra);
10080 break;
10081 case MP_STOP:
10082 RTW_INFO("set case mp_stop\n");
10083 status = rtw_mp_stop(dev, info, wrqu, extra);
10084 break;
10085 case MP_BANDWIDTH:
10086 RTW_INFO("set case mp_bandwidth\n");
10087 status = rtw_mp_bandwidth(dev, info, wrqu, extra);
10088 break;
10089 case MP_RESET_STATS:
10090 RTW_INFO("set case MP_RESET_STATS\n");
10091 status = rtw_mp_reset_stats(dev, info, wrqu, extra);
10092 break;
10093 case MP_SetRFPathSwh:
10094 RTW_INFO("set MP_SetRFPathSwitch\n");
10095 status = rtw_mp_SetRFPath(dev, info, wrqu, extra);
10096 break;
10097 case WRITE_REG:
10098 status = rtw_mp_write_reg(dev, info, wrqu, extra);
10099 break;
10100 case WRITE_RF:
10101 status = rtw_mp_write_rf(dev, info, wrqu, extra);
10102 break;
10103 case MP_PHYPARA:
10104 RTW_INFO("mp_get MP_PHYPARA\n");
10105 status = rtw_mp_phypara(dev, info, wrqu, extra);
10106 break;
10107 case MP_CHANNEL:
10108 RTW_INFO("set case mp_channel\n");
10109 status = rtw_mp_channel(dev , info, wrqu, extra);
10110 break;
10111 case MP_CHL_OFFSET:
10112 RTW_INFO("set case mp_ch_offset\n");
10113 status = rtw_mp_ch_offset(dev , info, wrqu, extra);
10114 break;
10115 case READ_REG:
10116 RTW_INFO("mp_get READ_REG\n");
10117 status = rtw_mp_read_reg(dev, info, wrqu, extra);
10118 break;
10119 case READ_RF:
10120 RTW_INFO("mp_get READ_RF\n");
10121 status = rtw_mp_read_rf(dev, info, wrqu, extra);
10122 break;
10123 case MP_RATE:
10124 RTW_INFO("set case mp_rate\n");
10125 status = rtw_mp_rate(dev, info, wrqu, extra);
10126 break;
10127 case MP_TXPOWER:
10128 RTW_INFO("set case MP_TXPOWER\n");
10129 status = rtw_mp_txpower(dev, info, wrqu, extra);
10130 break;
10131 case MP_ANT_TX:
10132 RTW_INFO("set case MP_ANT_TX\n");
10133 status = rtw_mp_ant_tx(dev, info, wrqu, extra);
10134 break;
10135 case MP_ANT_RX:
10136 RTW_INFO("set case MP_ANT_RX\n");
10137 status = rtw_mp_ant_rx(dev, info, wrqu, extra);
10138 break;
10139 case MP_QUERY:
10140 status = rtw_mp_trx_query(dev, info, wrqu, extra);
10141 break;
10142 case MP_CTX:
10143 RTW_INFO("set case MP_CTX\n");
10144 status = rtw_mp_ctx(dev, info, wrqu, extra);
10145 break;
10146 case MP_ARX:
10147 RTW_INFO("set case MP_ARX\n");
10148 status = rtw_mp_arx(dev, info, wrqu, extra);
10149 break;
10150 case MP_DUMP:
10151 RTW_INFO("set case MP_DUMP\n");
10152 status = rtw_mp_dump(dev, info, wrqu, extra);
10153 break;
10154 case MP_PSD:
10155 RTW_INFO("set case MP_PSD\n");
10156 status = rtw_mp_psd(dev, info, wrqu, extra);
10157 break;
10158 case MP_THER:
10159 RTW_INFO("set case MP_THER\n");
10160 status = rtw_mp_thermal(dev, info, wrqu, extra);
10161 break;
10162 case MP_PwrCtlDM:
10163 RTW_INFO("set MP_PwrCtlDM\n");
10164 status = rtw_mp_PwrCtlDM(dev, info, wrqu, extra);
10165 break;
10166 case MP_QueryDrvStats:
10167 RTW_INFO("mp_get MP_QueryDrvStats\n");
10168 status = rtw_mp_QueryDrv(dev, info, wdata, extra);
10169 break;
10170 case MP_PWRTRK:
10171 RTW_INFO("set case MP_PWRTRK\n");
10172 status = rtw_mp_pwrtrk(dev, info, wrqu, extra);
10173 break;
10174 case MP_SET_TSSIDE:
10175 RTW_INFO("set case MP_TSSI_DE\n");
10176 status = rtw_mp_set_tsside(dev, info, wrqu, extra);
10177 break;
10178 #ifdef CONFIG_MP_INCLUDED
10179 case EFUSE_SET:
10180 RTW_INFO("set case efuse set\n");
10181 status = rtw_mp_efuse_set(dev, info, wdata, extra);
10182 break;
10183 #endif
10184 case EFUSE_GET:
10185 RTW_INFO("efuse get EFUSE_GET\n");
10186 status = rtw_mp_efuse_get(dev, info, wdata, extra);
10187 break;
10188 case MP_GET_TXPOWER_INX:
10189 RTW_INFO("mp_get MP_GET_TXPOWER_INX\n");
10190 status = rtw_mp_txpower_index(dev, info, wrqu, extra);
10191 break;
10192 case MP_GETVER:
10193 RTW_INFO("mp_get MP_GETVER\n");
10194 status = rtw_mp_getver(dev, info, wdata, extra);
10195 break;
10196 case MP_MON:
10197 RTW_INFO("mp_get MP_MON\n");
10198 status = rtw_mp_mon(dev, info, wdata, extra);
10199 break;
10200 case EFUSE_BT_MASK:
10201 RTW_INFO("mp_get EFUSE_BT_MASK\n");
10202 status = rtw_bt_efuse_mask_file(dev, info, wdata, extra);
10203 break;
10204 case EFUSE_MASK:
10205 RTW_INFO("mp_get EFUSE_MASK\n");
10206 status = rtw_efuse_mask_file(dev, info, wdata, extra);
10207 break;
10208 case EFUSE_FILE:
10209 RTW_INFO("mp_get EFUSE_FILE\n");
10210 status = rtw_efuse_file_map(dev, info, wdata, extra);
10211 break;
10212 case EFUSE_FILE_STORE:
10213 RTW_INFO("mp_get EFUSE_FILE_STORE\n");
10214 status = rtw_efuse_file_map_store(dev, info, wdata, extra);
10215 break;
10216 case MP_TX:
10217 RTW_INFO("mp_get MP_TX\n");
10218 status = rtw_mp_tx(dev, info, wdata, extra);
10219 break;
10220 case MP_RX:
10221 RTW_INFO("mp_get MP_RX\n");
10222 status = rtw_mp_rx(dev, info, wdata, extra);
10223 break;
10224 case MP_HW_TX_MODE:
10225 RTW_INFO("mp_get MP_HW_TX_MODE\n");
10226 status = rtw_mp_hwtx(dev, info, wdata, extra);
10227 break;
10228 case MP_GET_TSSIDE:
10229 RTW_INFO("mp_get TSSI_DE\n");
10230 status = rtw_mp_get_tsside(dev, info, wrqu, extra);
10231 break;
10232 #ifdef CONFIG_RTW_CUSTOMER_STR
10233 case MP_CUSTOMER_STR:
10234 RTW_INFO("customer str\n");
10235 status = rtw_mp_customer_str(dev, info, wdata, extra);
10236 break;
10237 #endif
10238 case MP_PWRLMT:
10239 RTW_INFO("mp_get MP_SETPWRLMT\n");
10240 status = rtw_mp_pwrlmt(dev, info, wdata, extra);
10241 break;
10242 case MP_PWRBYRATE:
10243 RTW_INFO("mp_get MP_SETPWRBYRATE\n");
10244 status = rtw_mp_pwrbyrate(dev, info, wdata, extra);
10245 break;
10246 case BT_EFUSE_FILE:
10247 RTW_INFO("mp_get BT EFUSE_FILE\n");
10248 status = rtw_bt_efuse_file_map(dev, info, wdata, extra);
10249 break;
10250 case MP_SWRFPath:
10251 RTW_INFO("mp_get MP_SWRFPath\n");
10252 status = rtw_mp_switch_rf_path(dev, info, wrqu, extra);
10253 break;
10254 case MP_LINK:
10255 RTW_INFO("mp_get MP_LINK\n");
10256 status = rtw_mp_link(dev, info, wrqu, extra);
10257 break;
10258 case MP_DPK_TRK:
10259 RTW_INFO("mp_get MP_DPK_TRK\n");
10260 status = rtw_mp_dpk_track(dev, info, wdata, extra);
10261 break;
10262 case MP_DPK:
10263 RTW_INFO("set MP_DPK\n");
10264 status = rtw_mp_dpk(dev, info, wdata, extra);
10265 break;
10266 default:
10267 status = -EIO;
10268 }
10269
10270 _exit_critical_mutex(&(adapter_to_dvobj(padapter)->ioctrl_mutex), NULL);
10271 RTW_INFO("%s mutx done_%d\n", __func__, subcmd);
10272
10273 return status;
10274 }
10275 #endif /*#if defined(CONFIG_MP_INCLUDED)*/
10276
10277
10278 #ifdef CONFIG_SDIO_INDIRECT_ACCESS
10279 #define DBG_MP_SDIO_INDIRECT_ACCESS 1
10280 static int rtw_mp_sd_iread(struct net_device *dev
10281 , struct iw_request_info *info
10282 , struct iw_point *wrqu
10283 , char *extra)
10284 {
10285 char input[16];
10286 u8 width;
10287 unsigned long addr;
10288 u32 ret = 0;
10289 PADAPTER padapter = rtw_netdev_priv(dev);
10290
10291 if (wrqu->length > 16) {
10292 RTW_INFO(FUNC_ADPT_FMT" wrqu->length:%d\n", FUNC_ADPT_ARG(padapter), wrqu->length);
10293 ret = -EINVAL;
10294 goto exit;
10295 }
10296
10297 if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
10298 RTW_INFO(FUNC_ADPT_FMT" copy_from_user fail\n", FUNC_ADPT_ARG(padapter));
10299 ret = -EFAULT;
10300 goto exit;
10301 }
10302
10303 _rtw_memset(extra, 0, wrqu->length);
10304
10305 if (sscanf(input, "%hhu,%lx", &width, &addr) != 2) {
10306 RTW_INFO(FUNC_ADPT_FMT" sscanf fail\n", FUNC_ADPT_ARG(padapter));
10307 ret = -EINVAL;
10308 goto exit;
10309 }
10310
10311 if (addr > 0x3FFF) {
10312 RTW_INFO(FUNC_ADPT_FMT" addr:0x%lx\n", FUNC_ADPT_ARG(padapter), addr);
10313 ret = -EINVAL;
10314 goto exit;
10315 }
10316
10317 if (DBG_MP_SDIO_INDIRECT_ACCESS)
10318 RTW_INFO(FUNC_ADPT_FMT" width:%u, addr:0x%lx\n", FUNC_ADPT_ARG(padapter), width, addr);
10319
10320 switch (width) {
10321 case 1:
10322 sprintf(extra, "0x%02x", rtw_sd_iread8(padapter, addr));
10323 wrqu->length = strlen(extra);
10324 break;
10325 case 2:
10326 sprintf(extra, "0x%04x", rtw_sd_iread16(padapter, addr));
10327 wrqu->length = strlen(extra);
10328 break;
10329 case 4:
10330 sprintf(extra, "0x%08x", rtw_sd_iread32(padapter, addr));
10331 wrqu->length = strlen(extra);
10332 break;
10333 default:
10334 wrqu->length = 0;
10335 ret = -EINVAL;
10336 break;
10337 }
10338
10339 exit:
10340 return ret;
10341 }
10342
10343 static int rtw_mp_sd_iwrite(struct net_device *dev
10344 , struct iw_request_info *info
10345 , struct iw_point *wrqu
10346 , char *extra)
10347 {
10348 char width;
10349 unsigned long addr, data;
10350 int ret = 0;
10351 PADAPTER padapter = rtw_netdev_priv(dev);
10352 char input[32];
10353
10354 if (wrqu->length > 32) {
10355 RTW_INFO(FUNC_ADPT_FMT" wrqu->length:%d\n", FUNC_ADPT_ARG(padapter), wrqu->length);
10356 ret = -EINVAL;
10357 goto exit;
10358 }
10359
10360 if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
10361 RTW_INFO(FUNC_ADPT_FMT" copy_from_user fail\n", FUNC_ADPT_ARG(padapter));
10362 ret = -EFAULT;
10363 goto exit;
10364 }
10365
10366 _rtw_memset(extra, 0, wrqu->length);
10367
10368 if (sscanf(input, "%hhu,%lx,%lx", &width, &addr, &data) != 3) {
10369 RTW_INFO(FUNC_ADPT_FMT" sscanf fail\n", FUNC_ADPT_ARG(padapter));
10370 ret = -EINVAL;
10371 goto exit;
10372 }
10373
10374 if (addr > 0x3FFF) {
10375 RTW_INFO(FUNC_ADPT_FMT" addr:0x%lx\n", FUNC_ADPT_ARG(padapter), addr);
10376 ret = -EINVAL;
10377 goto exit;
10378 }
10379
10380 if (DBG_MP_SDIO_INDIRECT_ACCESS)
10381 RTW_INFO(FUNC_ADPT_FMT" width:%u, addr:0x%lx, data:0x%lx\n", FUNC_ADPT_ARG(padapter), width, addr, data);
10382
10383 switch (width) {
10384 case 1:
10385 if (data > 0xFF) {
10386 ret = -EINVAL;
10387 break;
10388 }
10389 rtw_sd_iwrite8(padapter, addr, data);
10390 break;
10391 case 2:
10392 if (data > 0xFFFF) {
10393 ret = -EINVAL;
10394 break;
10395 }
10396 rtw_sd_iwrite16(padapter, addr, data);
10397 break;
10398 case 4:
10399 rtw_sd_iwrite32(padapter, addr, data);
10400 break;
10401 default:
10402 wrqu->length = 0;
10403 ret = -EINVAL;
10404 break;
10405 }
10406
10407 exit:
10408 return ret;
10409 }
10410 #endif /* CONFIG_SDIO_INDIRECT_ACCESS */
10411
10412 static int rtw_priv_set(struct net_device *dev,
10413 struct iw_request_info *info,
10414 union iwreq_data *wdata, char *extra)
10415 {
10416 struct iw_point *wrqu = (struct iw_point *)wdata;
10417 u32 subcmd = wrqu->flags;
10418 PADAPTER padapter = rtw_netdev_priv(dev);
10419
10420 if (padapter == NULL)
10421 return -ENETDOWN;
10422
10423 if (padapter->bup == _FALSE) {
10424 RTW_INFO(" %s fail =>(padapter->bup == _FALSE )\n", __FUNCTION__);
10425 return -ENETDOWN;
10426 }
10427
10428 if (RTW_CANNOT_RUN(padapter)) {
10429 RTW_INFO("%s fail =>(bSurpriseRemoved == _TRUE) || ( bDriverStopped == _TRUE)\n", __func__);
10430 return -ENETDOWN;
10431 }
10432
10433 if (extra == NULL) {
10434 wrqu->length = 0;
10435 return -EIO;
10436 }
10437
10438 if (subcmd < MP_NULL) {
10439 #ifdef CONFIG_MP_INCLUDED
10440 rtw_priv_mp_set(dev, info, wdata, extra);
10441 #endif
10442 return 0;
10443 }
10444
10445 switch (subcmd) {
10446 #ifdef CONFIG_WOWLAN
10447 case MP_WOW_ENABLE:
10448 RTW_INFO("set case MP_WOW_ENABLE: %s\n", extra);
10449
10450 rtw_wowlan_ctrl(dev, info, wdata, extra);
10451 break;
10452 case MP_WOW_SET_PATTERN:
10453 RTW_INFO("set case MP_WOW_SET_PATTERN: %s\n", extra);
10454 rtw_wowlan_set_pattern(dev, info, wdata, extra);
10455 break;
10456 #endif
10457 #ifdef CONFIG_AP_WOWLAN
10458 case MP_AP_WOW_ENABLE:
10459 RTW_INFO("set case MP_AP_WOW_ENABLE: %s\n", extra);
10460 rtw_ap_wowlan_ctrl(dev, info, wdata, extra);
10461 break;
10462 #endif
10463 #ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
10464 case VENDOR_IE_SET:
10465 RTW_INFO("set case VENDOR_IE_SET\n");
10466 rtw_vendor_ie_set(dev , info , wdata , extra);
10467 break;
10468 #endif
10469 default:
10470 return -EIO;
10471 }
10472
10473 return 0;
10474 }
10475
10476
10477 static int rtw_priv_get(struct net_device *dev,
10478 struct iw_request_info *info,
10479 union iwreq_data *wdata, char *extra)
10480 {
10481 struct iw_point *wrqu = (struct iw_point *)wdata;
10482 u32 subcmd = wrqu->flags;
10483 PADAPTER padapter = rtw_netdev_priv(dev);
10484 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
10485 struct dm_struct *p_dm = &pHalData->odmpriv;
10486 struct dm_rf_calibration_struct *p_rf_calibrate_info = &(p_dm->rf_calibrate_info);
10487 struct dm_iqk_info *p_iqk_info = &p_dm->IQK_info;
10488 u32 i = 100;
10489
10490
10491 if (padapter->bup == _FALSE) {
10492 RTW_INFO(" %s fail =>(padapter->bup == _FALSE )\n", __FUNCTION__);
10493 return -ENETDOWN;
10494 }
10495
10496 if (RTW_CANNOT_RUN(padapter)) {
10497 RTW_INFO("%s fail =>(padapter->bSurpriseRemoved == _TRUE) || ( padapter->bDriverStopped == _TRUE)\n", __func__);
10498 return -ENETDOWN;
10499 }
10500
10501 if (extra == NULL) {
10502 wrqu->length = 0;
10503 return -EIO;
10504 }
10505
10506 if (subcmd < MP_NULL) {
10507 #ifdef CONFIG_MP_INCLUDED
10508 while (i > 1) {
10509 if (p_rf_calibrate_info->is_iqk_in_progress) {
10510 rtw_msleep_os(10);
10511 } else {
10512 p_iqk_info->rfk_forbidden = _TRUE;
10513 break;
10514 }
10515 i--;
10516 }
10517 if (subcmd == MP_CHANNEL || subcmd == MP_BANDWIDTH || subcmd == MP_START || subcmd == MP_DPK)
10518 p_iqk_info->rfk_forbidden = _FALSE;
10519 rtw_priv_mp_get(dev, info, wdata, extra);
10520 rtw_msleep_os(10); /* delay 5ms for sending pkt before exit adb shell operation */
10521 p_iqk_info->rfk_forbidden = _FALSE;
10522 #endif
10523 } else {
10524 switch (subcmd) {
10525 #if defined(CONFIG_RTL8723B)
10526 case MP_SetBT:
10527 RTW_INFO("set MP_SetBT\n");
10528 rtw_mp_SetBT(dev, info, wdata, extra);
10529 break;
10530 #endif
10531 #ifdef CONFIG_SDIO_INDIRECT_ACCESS
10532 case MP_SD_IREAD:
10533 rtw_mp_sd_iread(dev, info, wrqu, extra);
10534 break;
10535 case MP_SD_IWRITE:
10536 rtw_mp_sd_iwrite(dev, info, wrqu, extra);
10537 break;
10538 #endif
10539 #ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
10540 case VENDOR_IE_GET:
10541 RTW_INFO("get case VENDOR_IE_GET\n");
10542 rtw_vendor_ie_get(dev , info , wdata , extra);
10543 break;
10544 #endif
10545 default:
10546 return -EIO;
10547 }
10548 }
10549
10550 return 0;
10551 }
10552
10553
10554 #ifdef CONFIG_TDLS
10555 static int rtw_wx_tdls_wfd_enable(struct net_device *dev,
10556 struct iw_request_info *info,
10557 union iwreq_data *wrqu, char *extra)
10558 {
10559 int ret = 0;
10560
10561 #ifdef CONFIG_WFD
10562
10563 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10564
10565 RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
10566
10567 if (extra[0] == '0')
10568 rtw_tdls_wfd_enable(padapter, 0);
10569 else
10570 rtw_tdls_wfd_enable(padapter, 1);
10571
10572 #endif /* CONFIG_WFD */
10573
10574 return ret;
10575 }
10576
10577 static int rtw_tdls_weaksec(struct net_device *dev,
10578 struct iw_request_info *info,
10579 union iwreq_data *wrqu, char *extra)
10580 {
10581 int ret = 0;
10582
10583 #ifdef CONFIG_TDLS
10584
10585 u8 i, j;
10586 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10587
10588 RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
10589
10590 if (extra[0] == '0')
10591 padapter->wdinfo.wfd_tdls_weaksec = 0;
10592 else
10593 padapter->wdinfo.wfd_tdls_weaksec = 1;
10594
10595 #endif /* CONFIG_TDLS */
10596
10597 return ret;
10598 }
10599
10600
10601 static int rtw_tdls_enable(struct net_device *dev,
10602 struct iw_request_info *info,
10603 union iwreq_data *wrqu, char *extra)
10604 {
10605 int ret = 0;
10606
10607 #ifdef CONFIG_TDLS
10608 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10609
10610 RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
10611
10612 if (extra[0] == '0')
10613 rtw_disable_tdls_func(padapter, _TRUE);
10614 else if (extra[0] == '1')
10615 rtw_enable_tdls_func(padapter);
10616 #endif /* CONFIG_TDLS */
10617
10618 return ret;
10619 }
10620
10621 static int rtw_tdls_setup(struct net_device *dev,
10622 struct iw_request_info *info,
10623 union iwreq_data *wrqu, char *extra)
10624 {
10625 int ret = 0;
10626 #ifdef CONFIG_TDLS
10627 u8 i, j;
10628 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10629 struct tdls_txmgmt txmgmt;
10630 #ifdef CONFIG_WFD
10631 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
10632 #endif /* CONFIG_WFD */
10633
10634 RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
10635
10636 if (wrqu->data.length - 1 != 17) {
10637 RTW_INFO("[%s] length:%d != 17\n", __FUNCTION__, (wrqu->data.length - 1));
10638 return ret;
10639 }
10640
10641 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
10642 for (i = 0, j = 0 ; i < ETH_ALEN; i++, j += 3)
10643 txmgmt.peer[i] = key_2char2num(*(extra + j), *(extra + j + 1));
10644
10645 #ifdef CONFIG_WFD
10646 if (_AES_ != padapter->securitypriv.dot11PrivacyAlgrthm) {
10647 /* Weak Security situation with AP. */
10648 if (0 == pwdinfo->wfd_tdls_weaksec) {
10649 /* Can't send the tdls setup request out!! */
10650 RTW_INFO("[%s] Current link is not AES, "
10651 "SKIP sending the tdls setup request!!\n", __FUNCTION__);
10652 } else
10653 issue_tdls_setup_req(padapter, &txmgmt, _TRUE);
10654 } else
10655 #endif /* CONFIG_WFD */
10656 {
10657 issue_tdls_setup_req(padapter, &txmgmt, _TRUE);
10658 }
10659 #endif /* CONFIG_TDLS */
10660
10661 return ret;
10662 }
10663
10664 static int rtw_tdls_teardown(struct net_device *dev,
10665 struct iw_request_info *info,
10666 union iwreq_data *wrqu, char *extra)
10667 {
10668 int ret = 0;
10669
10670 #ifdef CONFIG_TDLS
10671
10672 u8 i, j;
10673 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10674 struct sta_info *ptdls_sta = NULL;
10675 struct tdls_txmgmt txmgmt;
10676
10677 RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
10678
10679 if (wrqu->data.length - 1 != 17 && wrqu->data.length - 1 != 19) {
10680 RTW_INFO("[%s] length:%d != 17 or 19\n",
10681 __FUNCTION__, (wrqu->data.length - 1));
10682 return ret;
10683 }
10684
10685 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
10686 for (i = 0, j = 0; i < ETH_ALEN; i++, j += 3)
10687 txmgmt.peer[i] = key_2char2num(*(extra + j), *(extra + j + 1));
10688
10689 ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), txmgmt.peer);
10690
10691 if (ptdls_sta != NULL) {
10692 txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_;
10693 if (wrqu->data.length - 1 == 19)
10694 issue_tdls_teardown(padapter, &txmgmt, _FALSE);
10695 else
10696 issue_tdls_teardown(padapter, &txmgmt, _TRUE);
10697 } else
10698 RTW_INFO("TDLS peer not found\n");
10699 #endif /* CONFIG_TDLS */
10700
10701 return ret;
10702 }
10703
10704 static int rtw_tdls_discovery(struct net_device *dev,
10705 struct iw_request_info *info,
10706 union iwreq_data *wrqu, char *extra)
10707 {
10708 int ret = 0;
10709
10710 #ifdef CONFIG_TDLS
10711
10712 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10713 struct tdls_txmgmt txmgmt;
10714 int i = 0, j = 0;
10715
10716 RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
10717
10718 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
10719 for (i = 0, j = 0 ; i < ETH_ALEN; i++, j += 3)
10720 txmgmt.peer[i] = key_2char2num(*(extra + j), *(extra + j + 1));
10721
10722 issue_tdls_dis_req(padapter, &txmgmt);
10723
10724 #endif /* CONFIG_TDLS */
10725
10726 return ret;
10727 }
10728
10729 static int rtw_tdls_ch_switch(struct net_device *dev,
10730 struct iw_request_info *info,
10731 union iwreq_data *wrqu, char *extra)
10732 {
10733 int ret = 0;
10734
10735 #ifdef CONFIG_TDLS
10736 #ifdef CONFIG_TDLS_CH_SW
10737 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10738 struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
10739 u8 i, j;
10740 struct sta_info *ptdls_sta = NULL;
10741 u8 take_care_iqk;
10742
10743 RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
10744
10745 if (rtw_tdls_is_chsw_allowed(padapter) == _FALSE) {
10746 RTW_INFO("TDLS channel switch is not allowed\n");
10747 return ret;
10748 }
10749
10750 for (i = 0, j = 0 ; i < ETH_ALEN; i++, j += 3)
10751 pchsw_info->addr[i] = key_2char2num(*(extra + j), *(extra + j + 1));
10752
10753 ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pchsw_info->addr);
10754 if (ptdls_sta == NULL)
10755 return ret;
10756
10757 pchsw_info->ch_sw_state |= TDLS_CH_SW_INITIATOR_STATE;
10758
10759 if (ptdls_sta != NULL) {
10760 if (pchsw_info->off_ch_num == 0)
10761 pchsw_info->off_ch_num = 11;
10762 } else
10763 RTW_INFO("TDLS peer not found\n");
10764
10765 rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
10766
10767 rtw_hal_get_hwreg(padapter, HW_VAR_CH_SW_NEED_TO_TAKE_CARE_IQK_INFO, &take_care_iqk);
10768 if (take_care_iqk == _TRUE) {
10769 u8 central_chnl;
10770 u8 bw_mode;
10771
10772 bw_mode = (pchsw_info->ch_offset) ? CHANNEL_WIDTH_40 : CHANNEL_WIDTH_20;
10773 central_chnl = rtw_get_center_ch(pchsw_info->off_ch_num, bw_mode, pchsw_info->ch_offset);
10774 if (rtw_hal_ch_sw_iqk_info_search(padapter, central_chnl, bw_mode) >= 0)
10775 rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_START);
10776 else
10777 rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_PREPARE);
10778 } else
10779 rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_START);
10780
10781 /* issue_tdls_ch_switch_req(padapter, ptdls_sta); */
10782 /* RTW_INFO("issue tdls ch switch req\n"); */
10783
10784 #endif /* CONFIG_TDLS_CH_SW */
10785 #endif /* CONFIG_TDLS */
10786
10787 return ret;
10788 }
10789
10790 static int rtw_tdls_ch_switch_off(struct net_device *dev,
10791 struct iw_request_info *info,
10792 union iwreq_data *wrqu, char *extra)
10793 {
10794 int ret = 0;
10795
10796 #ifdef CONFIG_TDLS
10797 #ifdef CONFIG_TDLS_CH_SW
10798
10799 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10800 struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
10801 u8 i, j, mac_addr[ETH_ALEN];
10802 struct sta_info *ptdls_sta = NULL;
10803 struct tdls_txmgmt txmgmt;
10804
10805 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
10806
10807 RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
10808
10809 if (rtw_tdls_is_chsw_allowed(padapter) == _FALSE) {
10810 RTW_INFO("TDLS channel switch is not allowed\n");
10811 return ret;
10812 }
10813
10814 if (wrqu->data.length >= 17) {
10815 for (i = 0, j = 0 ; i < ETH_ALEN; i++, j += 3)
10816 mac_addr[i] = key_2char2num(*(extra + j), *(extra + j + 1));
10817 ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
10818 }
10819
10820 if (ptdls_sta == NULL)
10821 return ret;
10822
10823 rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_END_TO_BASE_CHNL);
10824
10825 pchsw_info->ch_sw_state &= ~(TDLS_CH_SW_INITIATOR_STATE |
10826 TDLS_CH_SWITCH_ON_STATE |
10827 TDLS_PEER_AT_OFF_STATE);
10828 _rtw_memset(pchsw_info->addr, 0x00, ETH_ALEN);
10829
10830 ptdls_sta->ch_switch_time = 0;
10831 ptdls_sta->ch_switch_timeout = 0;
10832 _cancel_timer_ex(&ptdls_sta->ch_sw_timer);
10833 _cancel_timer_ex(&ptdls_sta->delay_timer);
10834 _cancel_timer_ex(&ptdls_sta->stay_on_base_chnl_timer);
10835 _cancel_timer_ex(&ptdls_sta->ch_sw_monitor_timer);
10836
10837 rtw_pm_set_lps(padapter, PS_MODE_MAX);
10838 #endif /* CONFIG_TDLS_CH_SW */
10839 #endif /* CONFIG_TDLS */
10840
10841 return ret;
10842 }
10843
10844 static int rtw_tdls_dump_ch(struct net_device *dev,
10845 struct iw_request_info *info,
10846 union iwreq_data *wrqu, char *extra)
10847 {
10848 int ret = 0;
10849
10850 #ifdef CONFIG_TDLS
10851 #ifdef CONFIG_TDLS_CH_SW
10852 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10853 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
10854
10855 RTW_INFO("[%s] dump_stack:%s\n", __FUNCTION__, extra);
10856
10857 extra[wrqu->data.length] = 0x00;
10858 ptdlsinfo->chsw_info.dump_stack = rtw_atoi(extra);
10859
10860 return ret;
10861
10862 #endif
10863 #endif /* CONFIG_TDLS */
10864
10865 return ret;
10866 }
10867
10868 static int rtw_tdls_off_ch_num(struct net_device *dev,
10869 struct iw_request_info *info,
10870 union iwreq_data *wrqu, char *extra)
10871 {
10872 int ret = 0;
10873
10874 #ifdef CONFIG_TDLS
10875 #ifdef CONFIG_TDLS_CH_SW
10876 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10877 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
10878
10879 RTW_INFO("[%s] off_ch_num:%s\n", __FUNCTION__, extra);
10880
10881 extra[wrqu->data.length] = 0x00;
10882 ptdlsinfo->chsw_info.off_ch_num = rtw_atoi(extra);
10883
10884 return ret;
10885
10886 #endif
10887 #endif /* CONFIG_TDLS */
10888
10889 return ret;
10890 }
10891
10892 static int rtw_tdls_ch_offset(struct net_device *dev,
10893 struct iw_request_info *info,
10894 union iwreq_data *wrqu, char *extra)
10895 {
10896 int ret = 0;
10897
10898 #ifdef CONFIG_TDLS
10899 #ifdef CONFIG_TDLS_CH_SW
10900 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10901 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
10902
10903 RTW_INFO("[%s] ch_offset:%s\n", __FUNCTION__, extra);
10904
10905 extra[wrqu->data.length] = 0x00;
10906 switch (rtw_atoi(extra)) {
10907 case SCA:
10908 ptdlsinfo->chsw_info.ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
10909 break;
10910
10911 case SCB:
10912 ptdlsinfo->chsw_info.ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
10913 break;
10914
10915 default:
10916 ptdlsinfo->chsw_info.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
10917 break;
10918 }
10919
10920 return ret;
10921
10922 #endif
10923 #endif /* CONFIG_TDLS */
10924
10925 return ret;
10926 }
10927
10928 static int rtw_tdls_pson(struct net_device *dev,
10929 struct iw_request_info *info,
10930 union iwreq_data *wrqu, char *extra)
10931 {
10932 int ret = 0;
10933
10934 #ifdef CONFIG_TDLS
10935
10936 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10937 u8 i, j, mac_addr[ETH_ALEN];
10938 struct sta_info *ptdls_sta = NULL;
10939
10940 RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
10941
10942 for (i = 0, j = 0; i < ETH_ALEN; i++, j += 3)
10943 mac_addr[i] = key_2char2num(*(extra + j), *(extra + j + 1));
10944
10945 ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
10946
10947 issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->cmn.mac_addr, 1, 3, 500);
10948
10949 #endif /* CONFIG_TDLS */
10950
10951 return ret;
10952 }
10953
10954 static int rtw_tdls_psoff(struct net_device *dev,
10955 struct iw_request_info *info,
10956 union iwreq_data *wrqu, char *extra)
10957 {
10958 int ret = 0;
10959
10960 #ifdef CONFIG_TDLS
10961
10962 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10963 u8 i, j, mac_addr[ETH_ALEN];
10964 struct sta_info *ptdls_sta = NULL;
10965
10966 RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
10967
10968 for (i = 0, j = 0; i < ETH_ALEN; i++, j += 3)
10969 mac_addr[i] = key_2char2num(*(extra + j), *(extra + j + 1));
10970
10971 ptdls_sta = rtw_get_stainfo(&padapter->stapriv, mac_addr);
10972
10973 if (ptdls_sta)
10974 issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->cmn.mac_addr, 0, 3, 500);
10975
10976 #endif /* CONFIG_TDLS */
10977
10978 return ret;
10979 }
10980
10981 static int rtw_tdls_setip(struct net_device *dev,
10982 struct iw_request_info *info,
10983 union iwreq_data *wrqu, char *extra)
10984 {
10985 int ret = 0;
10986
10987 #ifdef CONFIG_TDLS
10988 #ifdef CONFIG_WFD
10989
10990 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
10991 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
10992 struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
10993 u8 i = 0, j = 0, k = 0, tag = 0;
10994
10995 RTW_INFO("[%s] %s %d\n", __FUNCTION__, extra, wrqu->data.length - 1);
10996
10997 while (i < 4) {
10998 for (j = 0; j < 4; j++) {
10999 if (*(extra + j + tag) == '.' || *(extra + j + tag) == '\0') {
11000 if (j == 1)
11001 pwfd_info->ip_address[i] = convert_ip_addr('0', '0', *(extra + (j - 1) + tag));
11002 if (j == 2)
11003 pwfd_info->ip_address[i] = convert_ip_addr('0', *(extra + (j - 2) + tag), *(extra + (j - 1) + tag));
11004 if (j == 3)
11005 pwfd_info->ip_address[i] = convert_ip_addr(*(extra + (j - 3) + tag), *(extra + (j - 2) + tag), *(extra + (j - 1) + tag));
11006
11007 tag += j + 1;
11008 break;
11009 }
11010 }
11011 i++;
11012 }
11013
11014 RTW_INFO("[%s] Set IP = %u.%u.%u.%u\n", __FUNCTION__,
11015 ptdlsinfo->wfd_info->ip_address[0],
11016 ptdlsinfo->wfd_info->ip_address[1],
11017 ptdlsinfo->wfd_info->ip_address[2],
11018 ptdlsinfo->wfd_info->ip_address[3]);
11019
11020 #endif /* CONFIG_WFD */
11021 #endif /* CONFIG_TDLS */
11022
11023 return ret;
11024 }
11025
11026 static int rtw_tdls_getip(struct net_device *dev,
11027 struct iw_request_info *info,
11028 union iwreq_data *wrqu, char *extra)
11029 {
11030 int ret = 0;
11031
11032 #ifdef CONFIG_TDLS
11033 #ifdef CONFIG_WFD
11034
11035 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11036 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
11037 struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
11038
11039 RTW_INFO("[%s]\n", __FUNCTION__);
11040
11041 sprintf(extra, "\n\n%u.%u.%u.%u\n",
11042 pwfd_info->peer_ip_address[0], pwfd_info->peer_ip_address[1],
11043 pwfd_info->peer_ip_address[2], pwfd_info->peer_ip_address[3]);
11044
11045 RTW_INFO("[%s] IP=%u.%u.%u.%u\n", __FUNCTION__,
11046 pwfd_info->peer_ip_address[0], pwfd_info->peer_ip_address[1],
11047 pwfd_info->peer_ip_address[2], pwfd_info->peer_ip_address[3]);
11048
11049 wrqu->data.length = strlen(extra);
11050
11051 #endif /* CONFIG_WFD */
11052 #endif /* CONFIG_TDLS */
11053
11054 return ret;
11055 }
11056
11057 static int rtw_tdls_getport(struct net_device *dev,
11058 struct iw_request_info *info,
11059 union iwreq_data *wrqu, char *extra)
11060 {
11061
11062 int ret = 0;
11063
11064 #ifdef CONFIG_TDLS
11065 #ifdef CONFIG_WFD
11066
11067 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11068 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
11069 struct wifi_display_info *pwfd_info = ptdlsinfo->wfd_info;
11070
11071 RTW_INFO("[%s]\n", __FUNCTION__);
11072
11073 sprintf(extra, "\n\n%d\n", pwfd_info->peer_rtsp_ctrlport);
11074 RTW_INFO("[%s] remote port = %d\n",
11075 __FUNCTION__, pwfd_info->peer_rtsp_ctrlport);
11076
11077 wrqu->data.length = strlen(extra);
11078
11079 #endif /* CONFIG_WFD */
11080 #endif /* CONFIG_TDLS */
11081
11082 return ret;
11083
11084 }
11085
11086 /* WFDTDLS, for sigma test */
11087 static int rtw_tdls_dis_result(struct net_device *dev,
11088 struct iw_request_info *info,
11089 union iwreq_data *wrqu, char *extra)
11090 {
11091
11092 int ret = 0;
11093
11094 #ifdef CONFIG_TDLS
11095 #ifdef CONFIG_WFD
11096
11097 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11098 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
11099
11100 RTW_INFO("[%s]\n", __FUNCTION__);
11101
11102 if (ptdlsinfo->dev_discovered == _TRUE) {
11103 sprintf(extra, "\n\nDis=1\n");
11104 ptdlsinfo->dev_discovered = _FALSE;
11105 }
11106
11107 wrqu->data.length = strlen(extra);
11108
11109 #endif /* CONFIG_WFD */
11110 #endif /* CONFIG_TDLS */
11111
11112 return ret;
11113
11114 }
11115
11116 /* WFDTDLS, for sigma test */
11117 static int rtw_wfd_tdls_status(struct net_device *dev,
11118 struct iw_request_info *info,
11119 union iwreq_data *wrqu, char *extra)
11120 {
11121
11122 int ret = 0;
11123
11124 #ifdef CONFIG_TDLS
11125
11126 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11127 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
11128
11129 RTW_INFO("[%s]\n", __FUNCTION__);
11130
11131 sprintf(extra, "\nlink_established:%d\n"
11132 "sta_cnt:%d\n"
11133 "sta_maximum:%d\n"
11134 "cur_channel:%d\n"
11135 "tdls_enable:%d"
11136 #ifdef CONFIG_TDLS_CH_SW
11137 "ch_sw_state:%08x\n"
11138 "chsw_on:%d\n"
11139 "off_ch_num:%d\n"
11140 "cur_time:%d\n"
11141 "ch_offset:%d\n"
11142 "delay_swtich_back:%d"
11143 #endif
11144 ,
11145 ptdlsinfo->link_established, ptdlsinfo->sta_cnt,
11146 ptdlsinfo->sta_maximum, ptdlsinfo->cur_channel,
11147 rtw_is_tdls_enabled(padapter)
11148 #ifdef CONFIG_TDLS_CH_SW
11149 ,
11150 ptdlsinfo->chsw_info.ch_sw_state,
11151 ATOMIC_READ(&padapter->tdlsinfo.chsw_info.chsw_on),
11152 ptdlsinfo->chsw_info.off_ch_num,
11153 ptdlsinfo->chsw_info.cur_time,
11154 ptdlsinfo->chsw_info.ch_offset,
11155 ptdlsinfo->chsw_info.delay_switch_back
11156 #endif
11157 );
11158
11159 wrqu->data.length = strlen(extra);
11160
11161 #endif /* CONFIG_TDLS */
11162
11163 return ret;
11164
11165 }
11166
11167 static int rtw_tdls_getsta(struct net_device *dev,
11168 struct iw_request_info *info,
11169 union iwreq_data *wrqu, char *extra)
11170 {
11171
11172 int ret = 0;
11173 #ifdef CONFIG_TDLS
11174 u8 i, j;
11175 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11176 u8 addr[ETH_ALEN] = {0};
11177 char charmac[17];
11178 struct sta_info *ptdls_sta = NULL;
11179
11180 RTW_INFO("[%s] %s %d\n", __FUNCTION__,
11181 (char *)wrqu->data.pointer, wrqu->data.length - 1);
11182
11183 if (copy_from_user(charmac, wrqu->data.pointer + 9, 17)) {
11184 ret = -EFAULT;
11185 goto exit;
11186 }
11187
11188 RTW_INFO("[%s] %d, charmac:%s\n", __FUNCTION__, __LINE__, charmac);
11189 for (i = 0, j = 0 ; i < ETH_ALEN; i++, j += 3)
11190 addr[i] = key_2char2num(*(charmac + j), *(charmac + j + 1));
11191
11192 RTW_INFO("[%s] %d, charmac:%s, addr:"MAC_FMT"\n",
11193 __FUNCTION__, __LINE__, charmac, MAC_ARG(addr));
11194 ptdls_sta = rtw_get_stainfo(&padapter->stapriv, addr);
11195 if (ptdls_sta) {
11196 sprintf(extra, "\n\ntdls_sta_state=0x%08x\n", ptdls_sta->tdls_sta_state);
11197 RTW_INFO("\n\ntdls_sta_state=%d\n", ptdls_sta->tdls_sta_state);
11198 } else {
11199 sprintf(extra, "\n\nNot found this sta\n");
11200 RTW_INFO("\n\nNot found this sta\n");
11201 }
11202 wrqu->data.length = strlen(extra);
11203
11204 exit:
11205 #endif /* CONFIG_TDLS */
11206 return ret;
11207
11208 }
11209
11210 static int rtw_tdls_get_best_ch(struct net_device *dev,
11211 struct iw_request_info *info,
11212 union iwreq_data *wrqu, char *extra)
11213 {
11214 #ifdef CONFIG_FIND_BEST_CHANNEL
11215 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11216 struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
11217 u32 i, best_channel_24G = 1, best_channel_5G = 36, index_24G = 0, index_5G = 0;
11218
11219 for (i = 0; i < rfctl->max_chan_nums && rfctl->channel_set[i].ChannelNum != 0; i++) {
11220 if (rfctl->channel_set[i].ChannelNum == 1)
11221 index_24G = i;
11222 if (rfctl->channel_set[i].ChannelNum == 36)
11223 index_5G = i;
11224 }
11225
11226 for (i = 0; i < rfctl->max_chan_nums && rfctl->channel_set[i].ChannelNum != 0; i++) {
11227 /* 2.4G */
11228 if (rfctl->channel_set[i].ChannelNum == 6 || rfctl->channel_set[i].ChannelNum == 11) {
11229 if (rfctl->channel_set[i].rx_count < rfctl->channel_set[index_24G].rx_count) {
11230 index_24G = i;
11231 best_channel_24G = rfctl->channel_set[i].ChannelNum;
11232 }
11233 }
11234
11235 /* 5G */
11236 if (rfctl->channel_set[i].ChannelNum >= 36
11237 && rfctl->channel_set[i].ChannelNum < 140) {
11238 /* Find primary channel */
11239 if (((rfctl->channel_set[i].ChannelNum - 36) % 8 == 0)
11240 && (rfctl->channel_set[i].rx_count < rfctl->channel_set[index_5G].rx_count)) {
11241 index_5G = i;
11242 best_channel_5G = rfctl->channel_set[i].ChannelNum;
11243 }
11244 }
11245
11246 if (rfctl->channel_set[i].ChannelNum >= 149
11247 && rfctl->channel_set[i].ChannelNum < 165) {
11248 /* Find primary channel */
11249 if (((rfctl->channel_set[i].ChannelNum - 149) % 8 == 0)
11250 && (rfctl->channel_set[i].rx_count < rfctl->channel_set[index_5G].rx_count)) {
11251 index_5G = i;
11252 best_channel_5G = rfctl->channel_set[i].ChannelNum;
11253 }
11254 }
11255 #if 1 /* debug */
11256 RTW_INFO("The rx cnt of channel %3d = %d\n",
11257 rfctl->channel_set[i].ChannelNum,
11258 rfctl->channel_set[i].rx_count);
11259 #endif
11260 }
11261
11262 sprintf(extra, "\nbest_channel_24G = %d\n", best_channel_24G);
11263 RTW_INFO("best_channel_24G = %d\n", best_channel_24G);
11264
11265 if (index_5G != 0) {
11266 sprintf(extra, "best_channel_5G = %d\n", best_channel_5G);
11267 RTW_INFO("best_channel_5G = %d\n", best_channel_5G);
11268 }
11269
11270 wrqu->data.length = strlen(extra);
11271
11272 #endif
11273
11274 return 0;
11275
11276 }
11277 #endif /*#ifdef CONFIG_TDLS*/
11278 static int rtw_tdls(struct net_device *dev,
11279 struct iw_request_info *info,
11280 union iwreq_data *wrqu, char *extra)
11281 {
11282 int ret = 0;
11283
11284 #ifdef CONFIG_TDLS
11285
11286 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
11287
11288 RTW_INFO("[%s] extra = %s\n", __FUNCTION__, extra);
11289
11290 if (hal_chk_wl_func(padapter, WL_FUNC_TDLS) == _FALSE) {
11291 RTW_INFO("Discard tdls oper since hal doesn't support tdls\n");
11292 return 0;
11293 }
11294
11295 if (rtw_is_tdls_enabled(padapter) == _FALSE) {
11296 RTW_INFO("TDLS is not enabled\n");
11297 return 0;
11298 }
11299
11300 /* WFD Sigma will use the tdls enable command to let the driver know we want to test the tdls now! */
11301
11302 if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
11303 if (_rtw_memcmp(extra, "wfdenable=", 10)) {
11304 wrqu->data.length -= 10;
11305 rtw_wx_tdls_wfd_enable(dev, info, wrqu, &extra[10]);
11306 return ret;
11307 }
11308 }
11309
11310 if (_rtw_memcmp(extra, "weaksec=", 8)) {
11311 wrqu->data.length -= 8;
11312 rtw_tdls_weaksec(dev, info, wrqu, &extra[8]);
11313 return ret;
11314 } else if (_rtw_memcmp(extra, "tdlsenable=", 11)) {
11315 wrqu->data.length -= 11;
11316 rtw_tdls_enable(dev, info, wrqu, &extra[11]);
11317 return ret;
11318 }
11319
11320 if (_rtw_memcmp(extra, "setup=", 6)) {
11321 wrqu->data.length -= 6;
11322 rtw_tdls_setup(dev, info, wrqu, &extra[6]);
11323 } else if (_rtw_memcmp(extra, "tear=", 5)) {
11324 wrqu->data.length -= 5;
11325 rtw_tdls_teardown(dev, info, wrqu, &extra[5]);
11326 } else if (_rtw_memcmp(extra, "dis=", 4)) {
11327 wrqu->data.length -= 4;
11328 rtw_tdls_discovery(dev, info, wrqu, &extra[4]);
11329 } else if (_rtw_memcmp(extra, "swoff=", 6)) {
11330 wrqu->data.length -= 6;
11331 rtw_tdls_ch_switch_off(dev, info, wrqu, &extra[6]);
11332 } else if (_rtw_memcmp(extra, "sw=", 3)) {
11333 wrqu->data.length -= 3;
11334 rtw_tdls_ch_switch(dev, info, wrqu, &extra[3]);
11335 } else if (_rtw_memcmp(extra, "dumpstack=", 10)) {
11336 wrqu->data.length -= 10;
11337 rtw_tdls_dump_ch(dev, info, wrqu, &extra[10]);
11338 } else if (_rtw_memcmp(extra, "offchnum=", 9)) {
11339 wrqu->data.length -= 9;
11340 rtw_tdls_off_ch_num(dev, info, wrqu, &extra[9]);
11341 } else if (_rtw_memcmp(extra, "choffset=", 9)) {
11342 wrqu->data.length -= 9;
11343 rtw_tdls_ch_offset(dev, info, wrqu, &extra[9]);
11344 } else if (_rtw_memcmp(extra, "pson=", 5)) {
11345 wrqu->data.length -= 5;
11346 rtw_tdls_pson(dev, info, wrqu, &extra[5]);
11347 } else if (_rtw_memcmp(extra, "psoff=", 6)) {
11348 wrqu->data.length -= 6;
11349 rtw_tdls_psoff(dev, info, wrqu, &extra[6]);
11350 }
11351
11352 #ifdef CONFIG_WFD
11353 if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
11354 if (_rtw_memcmp(extra, "setip=", 6)) {
11355 wrqu->data.length -= 6;
11356 rtw_tdls_setip(dev, info, wrqu, &extra[6]);
11357 } else if (_rtw_memcmp(extra, "tprobe=", 6))
11358 issue_tunneled_probe_req((_adapter *)rtw_netdev_priv(dev));
11359 }
11360 #endif /* CONFIG_WFD */
11361
11362 #endif /* CONFIG_TDLS */
11363
11364 return ret;
11365 }
11366
11367
11368 static int rtw_tdls_get(struct net_device *dev,
11369 struct iw_request_info *info,
11370 union iwreq_data *wrqu, char *extra)
11371 {
11372 int ret = 0;
11373
11374 #ifdef CONFIG_TDLS
11375
11376 RTW_INFO("[%s] extra = %s\n", __FUNCTION__, (char *) wrqu->data.pointer);
11377
11378 if (_rtw_memcmp(wrqu->data.pointer, "ip", 2))
11379 rtw_tdls_getip(dev, info, wrqu, extra);
11380 else if (_rtw_memcmp(wrqu->data.pointer, "port", 4))
11381 rtw_tdls_getport(dev, info, wrqu, extra);
11382 /* WFDTDLS, for sigma test */
11383 else if (_rtw_memcmp(wrqu->data.pointer, "dis", 3))
11384 rtw_tdls_dis_result(dev, info, wrqu, extra);
11385 else if (_rtw_memcmp(wrqu->data.pointer, "status", 6))
11386 rtw_wfd_tdls_status(dev, info, wrqu, extra);
11387 else if (_rtw_memcmp(wrqu->data.pointer, "tdls_sta=", 9))
11388 rtw_tdls_getsta(dev, info, wrqu, extra);
11389 else if (_rtw_memcmp(wrqu->data.pointer, "best_ch", 7))
11390 rtw_tdls_get_best_ch(dev, info, wrqu, extra);
11391 #endif /* CONFIG_TDLS */
11392
11393 return ret;
11394 }
11395
11396 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
11397
11398 #if defined(CONFIG_RTL8188E)
11399 #include <rtl8188e_hal.h>
11400 extern void rtl8188e_cal_txdesc_chksum(struct tx_desc *ptxdesc);
11401 #define cal_txdesc_chksum(padapter, desc) rtl8188e_cal_txdesc_chksum(desc)
11402 #ifdef CONFIG_SDIO_HCI || defined(CONFIG_GSPI_HCI)
11403 extern void rtl8188es_fill_default_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf);
11404 #define fill_default_txdesc rtl8188es_fill_default_txdesc
11405 #endif /* CONFIG_SDIO_HCI */
11406 #endif /* CONFIG_RTL8188E */
11407 #if defined(CONFIG_RTL8723B)
11408 extern void rtl8723b_cal_txdesc_chksum(struct tx_desc *ptxdesc);
11409 #define cal_txdesc_chksum(padapter, desc) rtl8723b_cal_txdesc_chksum(desc)
11410 extern void rtl8723b_fill_default_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf);
11411 #define fill_default_txdesc rtl8723b_fill_default_txdesc
11412 #endif /* CONFIG_RTL8723B */
11413
11414 #if defined(CONFIG_RTL8703B)
11415 /* extern void rtl8703b_cal_txdesc_chksum(struct tx_desc *ptxdesc); */
11416 #define cal_txdesc_chksum(padapter, desc) rtl8703b_cal_txdesc_chksum(desc)
11417 /* extern void rtl8703b_fill_default_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf); */
11418 #define fill_default_txdesc rtl8703b_fill_default_txdesc
11419 #endif /* CONFIG_RTL8703B */
11420
11421 #if defined(CONFIG_RTL8723D)
11422 /* extern void rtl8723d_cal_txdesc_chksum(struct tx_desc *ptxdesc); */
11423 #define cal_txdesc_chksum(padapter, desc) rtl8723d_cal_txdesc_chksum(desc)
11424 /* extern void rtl8723d_fill_default_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf); */
11425 #define fill_default_txdesc rtl8723d_fill_default_txdesc
11426 #endif /* CONFIG_RTL8723D */
11427
11428 #if defined(CONFIG_RTL8710B)
11429 #define cal_txdesc_chksum(padapter, desc) rtl8710b_cal_txdesc_chksum(desc)
11430 #define fill_default_txdesc rtl8710b_fill_default_txdesc
11431 #endif /* CONFIG_RTL8710B */
11432
11433 #if defined(CONFIG_RTL8192E)
11434 extern void rtl8192e_cal_txdesc_chksum(struct tx_desc *ptxdesc);
11435 #define cal_txdesc_chksum(padapter, desc) rtl8192e_cal_txdesc_chksum(desc)
11436 #ifdef CONFIG_SDIO_HCI || defined(CONFIG_GSPI_HCI)
11437 extern void rtl8192es_fill_default_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf);
11438 #define fill_default_txdesc rtl8192es_fill_default_txdesc
11439 #endif /* CONFIG_SDIO_HCI */
11440 #endif /* CONFIG_RTL8192E */
11441
11442 #if defined(CONFIG_RTL8192F)
11443 /* extern void rtl8192f_cal_txdesc_chksum(struct tx_desc *ptxdesc); */
11444 #define cal_txdesc_chksum(padapter, desc) rtl8192f_cal_txdesc_chksum(desc)
11445 /* extern void rtl8192f_fill_default_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf); */
11446 #define fill_default_txdesc rtl8192f_fill_default_txdesc
11447 #endif /* CONFIG_RTL8192F */
11448
11449 #ifdef CONFIG_RTL8723F
11450 #include <../../hal/rtl8723f/rtl8723f.h>
11451
11452 #define REG_LOOPBACK_ENABLE 0x0103
11453 #define LOOKBACK_ENABLE_VALUE 0x0b
11454 #define cal_txdesc_chksum(padapter, desc) rtl8723f_cal_txdesc_chksum(padapter, desc)
11455 #define dump_txdesc_data(padapter, desc) rtl8723f_dbg_dump_tx_desc(padapter, DATA_FRAMETAG, desc);
11456 #define get_rx_desc(rx_desc, rxbuf) rtl8723f_rxdesc2attribute(rx_desc, rxbuf)
11457 #define hal_init rtl8723f_hal_init
11458 #endif /* CONFIG_RTL8723F */
11459
11460 void dbg_dump_pkt(char *s, u8 *buf, u8 len)
11461 {
11462 u8 i, j = 1;
11463
11464 RTW_INFO("%s size = %u\n", s, len);
11465
11466 for (i = 0; (i + 4) < len; i += 4) {
11467 if (j % 4 == 1)
11468 RTW_PRINT("idx:%u:", i);
11469 _RTW_PRINT(" 0x%02x 0x%02x 0x%02x 0x%02x", buf[i], buf[i+1], buf[i+2], buf[i+3]);
11470 if ((j++) % 4 == 0)
11471 _RTW_PRINT("\n");
11472 }
11473
11474 for (; i < len ; i++) {
11475 _RTW_PRINT(" 0x%02x", buf[i]);
11476 }
11477 _RTW_PRINT("\n ================================\n");
11478 }
11479
11480 static s32 initLoopback(PADAPTER padapter)
11481 {
11482 PLOOPBACKDATA ploopback;
11483
11484 if (padapter->ploopback == NULL) {
11485 ploopback = (PLOOPBACKDATA)rtw_zmalloc(sizeof(LOOPBACKDATA));
11486 if (ploopback == NULL)
11487 return -ENOMEM;
11488
11489 _rtw_init_sema(&ploopback->sema, 0);
11490 ploopback->bstop = _TRUE;
11491 ploopback->cnt = 0;
11492 ploopback->size = 300;
11493 _rtw_memset(ploopback->msg, 0, sizeof(ploopback->msg));
11494
11495 padapter->ploopback = ploopback;
11496 }
11497
11498 return 0;
11499 }
11500
11501 static void freeLoopback(PADAPTER padapter)
11502 {
11503 PLOOPBACKDATA ploopback;
11504
11505 ploopback = padapter->ploopback;
11506 if (ploopback) {
11507 rtw_mfree((u8 *)ploopback, sizeof(LOOPBACKDATA));
11508 padapter->ploopback = NULL;
11509 }
11510 }
11511
11512 static s32 initpseudoadhoc(PADAPTER padapter)
11513 {
11514 NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
11515 s32 err;
11516
11517 networkType = Ndis802_11IBSS;
11518 err = rtw_set_802_11_infrastructure_mode(padapter, networkType, 0);
11519 if (err == _FALSE)
11520 return _FAIL;
11521
11522 err = rtw_setopmode_cmd(padapter, networkType, RTW_CMDF_WAIT_ACK);
11523 if (err == _FAIL)
11524 return _FAIL;
11525
11526 return _SUCCESS;
11527 }
11528
11529 static s32 createpseudoadhoc(PADAPTER padapter)
11530 {
11531 NDIS_802_11_AUTHENTICATION_MODE authmode;
11532 struct mlme_priv *pmlmepriv;
11533 NDIS_802_11_SSID *passoc_ssid;
11534 WLAN_BSSID_EX *pdev_network;
11535 u8 *pibss;
11536 u8 ssid[] = "pseduo_ad-hoc";
11537 s32 err;
11538 _irqL irqL;
11539
11540 pmlmepriv = &padapter->mlmepriv;
11541
11542 authmode = Ndis802_11AuthModeOpen;
11543 err = rtw_set_802_11_authentication_mode(padapter, authmode);
11544 if (err == _FALSE)
11545 return _FAIL;
11546
11547 passoc_ssid = &pmlmepriv->assoc_ssid;
11548 _rtw_memset(passoc_ssid, 0, sizeof(NDIS_802_11_SSID));
11549 passoc_ssid->SsidLength = sizeof(ssid) - 1;
11550 _rtw_memcpy(passoc_ssid->Ssid, ssid, passoc_ssid->SsidLength);
11551
11552 pdev_network = &padapter->registrypriv.dev_network;
11553 pibss = padapter->registrypriv.dev_network.MacAddress;
11554 _rtw_memcpy(&pdev_network->Ssid, passoc_ssid, sizeof(NDIS_802_11_SSID));
11555
11556 rtw_update_registrypriv_dev_network(padapter);
11557 rtw_generate_random_ibss(pibss);
11558
11559 _enter_critical_bh(&pmlmepriv->lock, &irqL);
11560 /*pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;*/
11561 init_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
11562
11563 _exit_critical_bh(&pmlmepriv->lock, &irqL);
11564
11565 #if 0
11566 err = rtw_create_ibss_cmd(padapter, 0);
11567 if (err == _FAIL)
11568 return _FAIL;
11569 #else
11570 {
11571 struct wlan_network *pcur_network;
11572 struct sta_info *psta;
11573
11574 /* 3 create a new psta */
11575 pcur_network = &pmlmepriv->cur_network;
11576
11577 /* clear psta in the cur_network, if any */
11578 psta = rtw_get_stainfo(&padapter->stapriv, pcur_network->network.MacAddress);
11579 if (psta)
11580 rtw_free_stainfo(padapter, psta);
11581
11582 psta = rtw_alloc_stainfo(&padapter->stapriv, pibss);
11583 if (psta == NULL)
11584 return _FAIL;
11585
11586 /* 3 join psudo AdHoc */
11587 pcur_network->join_res = 1;
11588 pcur_network->aid = psta->cmn.aid = 1;
11589 _rtw_memcpy(&pcur_network->network, pdev_network, get_WLAN_BSSID_EX_sz(pdev_network));
11590
11591 /* set msr to WIFI_FW_ADHOC_STATE */
11592 padapter->hw_port = HW_PORT0;
11593 Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
11594
11595 }
11596 #endif
11597
11598 return _SUCCESS;
11599 }
11600
11601 static struct xmit_frame *createloopbackpkt(PADAPTER padapter, u32 size)
11602 {
11603 struct xmit_priv *pxmitpriv;
11604 struct xmit_frame *pframe;
11605 struct xmit_buf *pxmitbuf;
11606 struct pkt_attrib *pattrib;
11607 struct tx_desc *desc;
11608 u8 *pkt_start, *pkt_end, *ptr;
11609 struct rtw_ieee80211_hdr *hdr;
11610 s32 bmcast;
11611 _irqL irqL;
11612
11613
11614 if ((TXDESC_SIZE + WLANHDR_OFFSET + size) > MAX_XMITBUF_SZ)
11615 return NULL;
11616
11617 pxmitpriv = &padapter->xmitpriv;
11618 pframe = NULL;
11619
11620 /* 2 1. allocate xmit frame */
11621 pframe = rtw_alloc_xmitframe(pxmitpriv, 0);
11622 if (pframe == NULL)
11623 return NULL;
11624 pframe->padapter = padapter;
11625
11626 /* 2 2. allocate xmit buffer */
11627 _enter_critical_bh(&pxmitpriv->lock, &irqL);
11628 pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
11629 _exit_critical_bh(&pxmitpriv->lock, &irqL);
11630 if (pxmitbuf == NULL) {
11631 rtw_free_xmitframe(pxmitpriv, pframe);
11632 return NULL;
11633 }
11634
11635 pframe->pxmitbuf = pxmitbuf;
11636 pframe->buf_addr = pxmitbuf->pbuf;
11637 pxmitbuf->priv_data = pframe;
11638
11639 /* 2 3. update_attrib() */
11640 pattrib = &pframe->attrib;
11641
11642 /* init xmitframe attribute */
11643 _rtw_memset(pattrib, 0, sizeof(struct pkt_attrib));
11644
11645 pattrib->ether_type = 0x8723;
11646 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
11647 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
11648 _rtw_memset(pattrib->dst, 0xFF, ETH_ALEN);
11649 _rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
11650
11651 /* pattrib->dhcp_pkt = 0;
11652 * pattrib->pktlen = 0; */
11653 pattrib->ack_policy = 0;
11654 /* pattrib->pkt_hdrlen = ETH_HLEN; */
11655 pattrib->hdrlen = WLAN_HDR_A3_LEN;
11656 pattrib->subtype = WIFI_DATA;
11657 pattrib->priority = 0;
11658 pattrib->qsel = pattrib->priority;
11659 /* do_queue_select(padapter, pattrib); */
11660 pattrib->nr_frags = 1;
11661 pattrib->encrypt = 0;
11662 pattrib->bswenc = _FALSE;
11663 pattrib->qos_en = _FALSE;
11664
11665 bmcast = IS_MCAST(pattrib->ra);
11666 if (bmcast)
11667 pattrib->psta = rtw_get_bcmc_stainfo(padapter);
11668 else
11669 pattrib->psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(&padapter->mlmepriv));
11670
11671 pattrib->mac_id = pattrib->psta->cmn.mac_id;
11672 pattrib->pktlen = size;
11673 pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->pktlen;
11674
11675 /* 2 4. fill TX descriptor */
11676 desc = (struct tx_desc *)pframe->buf_addr;
11677 _rtw_memset(desc, 0, TXDESC_SIZE);
11678
11679 fill_default_txdesc(pframe, (u8 *)desc);
11680
11681 #if 0
11682 /* Hw set sequence number */
11683 ((PTXDESC)desc)->hwseq_en = 0; /* HWSEQ_EN, 0:disable, 1:enable
11684 * ((PTXDESC)desc)->hwseq_sel = 0; */ /* HWSEQ_SEL */
11685
11686 ((PTXDESC)desc)->disdatafb = 1;
11687
11688 /* convert to little endian */
11689 desc->txdw0 = cpu_to_le32(desc->txdw0);
11690 desc->txdw1 = cpu_to_le32(desc->txdw1);
11691 desc->txdw2 = cpu_to_le32(desc->txdw2);
11692 desc->txdw3 = cpu_to_le32(desc->txdw3);
11693 desc->txdw4 = cpu_to_le32(desc->txdw4);
11694 desc->txdw5 = cpu_to_le32(desc->txdw5);
11695 desc->txdw6 = cpu_to_le32(desc->txdw6);
11696 desc->txdw7 = cpu_to_le32(desc->txdw7);
11697 #ifdef CONFIG_PCI_HCI
11698 desc->txdw8 = cpu_to_le32(desc->txdw8);
11699 desc->txdw9 = cpu_to_le32(desc->txdw9);
11700 desc->txdw10 = cpu_to_le32(desc->txdw10);
11701 desc->txdw11 = cpu_to_le32(desc->txdw11);
11702 desc->txdw12 = cpu_to_le32(desc->txdw12);
11703 desc->txdw13 = cpu_to_le32(desc->txdw13);
11704 desc->txdw14 = cpu_to_le32(desc->txdw14);
11705 desc->txdw15 = cpu_to_le32(desc->txdw15);
11706 #endif
11707 #endif
11708
11709 cal_txdesc_chksum(padapter, (u8*)desc);
11710 /* dump_txdesc_data(padapter, (u8*)desc); */
11711
11712 /* 2 5. coalesce */
11713 pkt_start = pframe->buf_addr + TXDESC_SIZE;
11714 pkt_end = pkt_start + pattrib->last_txcmdsz;
11715
11716 /* 3 5.1. make wlan header, make_wlanhdr() */
11717 hdr = (struct rtw_ieee80211_hdr *)pkt_start;
11718 set_frame_sub_type(&hdr->frame_ctl, pattrib->subtype);
11719 _rtw_memcpy(hdr->addr1, pattrib->dst, ETH_ALEN); /* DA */
11720 _rtw_memcpy(hdr->addr2, pattrib->src, ETH_ALEN); /* SA */
11721 _rtw_memcpy(hdr->addr3, get_bssid(&padapter->mlmepriv), ETH_ALEN); /* RA, BSSID */
11722
11723 /* 3 5.2. make payload */
11724 ptr = pkt_start + pattrib->hdrlen;
11725 get_random_bytes(ptr, pkt_end - ptr);
11726
11727 pxmitbuf->len = TXDESC_SIZE + pattrib->last_txcmdsz;
11728 #if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
11729 pxmitbuf->ptail += pxmitbuf->len;
11730 #endif
11731
11732 dbg_dump_pkt("TX packet", pxmitbuf->pbuf, pxmitbuf->len);
11733
11734 return pframe;
11735 }
11736
11737 static void freeloopbackpkt(PADAPTER padapter, struct xmit_frame *pframe)
11738 {
11739 struct xmit_priv *pxmitpriv;
11740 struct xmit_buf *pxmitbuf;
11741
11742 pxmitpriv = &padapter->xmitpriv;
11743 pxmitbuf = pframe->pxmitbuf;
11744
11745 rtw_free_xmitframe(pxmitpriv, pframe);
11746 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
11747 }
11748
11749 static void printdata(u8 *pbuf, u32 len)
11750 {
11751 u32 i, val;
11752
11753 for (i = 0; (i + 4) <= len; i += 4) {
11754 printk("%08X", *(u32 *)(pbuf + i));
11755 if ((i + 4) & 0x1F)
11756 printk(" ");
11757 else
11758 printk("\n");
11759 }
11760
11761 if (i < len) {
11762 #ifdef CONFIG_BIG_ENDIAN
11763 for (; i < len, i++)
11764 printk("%02X", pbuf + i);
11765 #else /* CONFIG_LITTLE_ENDIAN */
11766 #if 0
11767 val = 0;
11768 _rtw_memcpy(&val, pbuf + i, len - i);
11769 printk("%8X", val);
11770 #else
11771 u8 str[9];
11772 u8 n;
11773 val = 0;
11774 n = len - i;
11775 _rtw_memcpy(&val, pbuf + i, n);
11776 sprintf(str, "%08X", val);
11777 n = (4 - n) * 2;
11778 printk("%8s", str + n);
11779 #endif
11780 #endif /* CONFIG_LITTLE_ENDIAN */
11781 }
11782 printk("\n");
11783 }
11784
11785 static u8 pktcmp(PADAPTER padapter, u8 *txbuf, u32 txsz, u8 *rxbuf, u32 rxsz)
11786 {
11787 struct rx_pkt_attrib rx_desc;
11788 #if 0
11789 struct recv_stat *prxstat;
11790 struct recv_stat report;
11791 PRXREPORT prxreport;
11792 #endif
11793 u32 rxpktsize;
11794 u8 drvinfosize;
11795 u8 shiftsize;
11796 u8 ret = _FALSE;
11797 u8 skip_len = 4; /* Don't compare the frame control and duration field */
11798 get_rx_desc(&rx_desc, rxbuf);
11799 rxpktsize = rx_desc.pkt_len;
11800 drvinfosize = rx_desc.drvinfo_sz;
11801 shiftsize = rx_desc.shift_sz;
11802
11803 #if 0
11804 prxstat = (struct recv_stat *)rxbuf;
11805 report.rxdw0 = le32_to_cpu(prxstat->rxdw0);
11806 report.rxdw1 = le32_to_cpu(prxstat->rxdw1);
11807 report.rxdw2 = le32_to_cpu(prxstat->rxdw2);
11808 report.rxdw3 = le32_to_cpu(prxstat->rxdw3);
11809 report.rxdw4 = le32_to_cpu(prxstat->rxdw4);
11810 report.rxdw5 = le32_to_cpu(prxstat->rxdw5);
11811
11812 prxreport = (PRXREPORT)&report;
11813 drvinfosize = prxreport->drvinfosize << 3;
11814 rxpktsize = prxreport->pktlen;
11815 #endif
11816
11817 if (rtw_hal_rcr_check(padapter, RCR_APPFCS))
11818 rxpktsize -= IEEE80211_FCS_LEN;
11819
11820 if ((txsz - TXDESC_SIZE) != rxpktsize) {
11821 RTW_INFO("%s: ERROR! size not match tx/rx=%d/%d !\n",
11822 __func__, txsz - TXDESC_SIZE, rxpktsize);
11823 ret = _FALSE;
11824 } else {
11825 ret = _rtw_memcmp(txbuf + TXDESC_SIZE + skip_len, \
11826 rxbuf + RXDESC_SIZE + skip_len + drvinfosize, \
11827 txsz - TXDESC_SIZE - skip_len);
11828 if (ret == _FALSE)
11829 RTW_INFO("%s: ERROR! pkt content mismatch!\n", __func__);
11830 }
11831
11832 if (ret == _FALSE) {
11833 RTW_INFO("\n%s: TX PKT total=%d, desc=%d, content=%d\n",
11834 __func__, txsz, TXDESC_SIZE, txsz - TXDESC_SIZE);
11835 dbg_dump_pkt("TX DESC", txbuf, TXDESC_SIZE);
11836 dbg_dump_pkt("TX content", txbuf + TXDESC_SIZE, txsz - TXDESC_SIZE);
11837
11838 RTW_INFO("\n%s: RX PKT read=%d offset=%d(%d,%d) content=%d\n",
11839 __func__, rxsz, RXDESC_SIZE + drvinfosize, RXDESC_SIZE, drvinfosize, rxpktsize);
11840 if (rxpktsize != 0) {
11841 dbg_dump_pkt("RX DESC", rxbuf, RXDESC_SIZE);
11842 dbg_dump_pkt("RX drvinfo", rxbuf + RXDESC_SIZE, drvinfosize);
11843 dbg_dump_pkt("RX packet content", rxbuf + RXDESC_SIZE + drvinfosize, rxpktsize);
11844 } else {
11845 RTW_INFO("%s: RX data size=%d\n", __func__, rxsz);
11846 }
11847 }
11848
11849 return ret;
11850 }
11851
11852 thread_return lbk_thread(thread_context context)
11853 {
11854 s32 err;
11855 PADAPTER padapter;
11856 PLOOPBACKDATA ploopback;
11857 struct xmit_frame *pxmitframe;
11858 u32 cnt, ok, fail, headerlen;
11859 u32 pktsize;
11860 u32 ff_hwaddr;
11861
11862 padapter = (PADAPTER)context;
11863 ploopback = padapter->ploopback;
11864 if (ploopback == NULL)
11865 return -1;
11866 cnt = 0;
11867 ok = 0;
11868 fail = 0;
11869
11870 thread_enter("RTW_LBK_THREAD");
11871 /* daemonize("%s", "RTW_LBK_THREAD"); */
11872 allow_signal(SIGTERM);
11873
11874 do {
11875 if (ploopback->size == 0) {
11876 get_random_bytes(&pktsize, 4);
11877 pktsize = (pktsize % 1535) + 1; /* 1~1535 */
11878 } else
11879 pktsize = ploopback->size;
11880
11881 pxmitframe = createloopbackpkt(padapter, pktsize);
11882 if (pxmitframe == NULL) {
11883 sprintf(ploopback->msg, "loopback FAIL! 3. create Packet FAIL!");
11884 break;
11885 }
11886
11887 ploopback->txsize = TXDESC_SIZE + pxmitframe->attrib.last_txcmdsz;
11888 _rtw_memcpy(ploopback->txbuf, pxmitframe->buf_addr, ploopback->txsize);
11889 ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
11890 cnt++;
11891 RTW_INFO("%s: wirte port cnt=%d size=%d\n", __func__, cnt, ploopback->txsize);
11892 #if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
11893 pxmitframe->pxmitbuf->pdata = ploopback->txbuf;
11894 #endif
11895 rtw_write_port(padapter, ff_hwaddr, ploopback->txsize, (u8 *)pxmitframe->pxmitbuf);
11896
11897 /* wait for rx pkt */
11898 RTW_INFO("%s: wait for rx packet\n", __func__);
11899 _rtw_down_sema(&ploopback->sema);
11900
11901 err = pktcmp(padapter, ploopback->txbuf, ploopback->txsize, ploopback->rxbuf, ploopback->rxsize);
11902 if (err == _TRUE)
11903 ok++;
11904 else
11905 fail++;
11906
11907 ploopback->txsize = 0;
11908 _rtw_memset(ploopback->txbuf, 0, 0x8000);
11909 ploopback->rxsize = 0;
11910 _rtw_memset(ploopback->rxbuf, 0, 0x8000);
11911
11912 freeloopbackpkt(padapter, pxmitframe);
11913 pxmitframe = NULL;
11914
11915 flush_signals_thread();
11916
11917 if ((ploopback->bstop == _TRUE) ||
11918 ((ploopback->cnt != 0) && (ploopback->cnt == cnt))) {
11919 u32 ok_rate, fail_rate, all;
11920 all = cnt;
11921 ok_rate = (ok * 100) / all;
11922 fail_rate = (fail * 100) / all;
11923 sprintf(ploopback->msg, \
11924 "loopback result: ok=%d%%(%d/%d),error=%d%%(%d/%d)", \
11925 ok_rate, ok, all, fail_rate, fail, all);
11926 break;
11927 }
11928 } while (1);
11929
11930 ploopback->bstop = _TRUE;
11931
11932 thread_exit(NULL);
11933 return 0;
11934 }
11935
11936 static void loopbackTest(PADAPTER padapter, u32 cnt, u32 size, u8 *pmsg)
11937 {
11938 PLOOPBACKDATA ploopback;
11939 u32 len;
11940 s32 err;
11941
11942 ploopback = padapter->ploopback;
11943
11944 if (ploopback) {
11945 if (ploopback->bstop == _FALSE) {
11946 ploopback->bstop = _TRUE;
11947 _rtw_up_sema(&ploopback->sema);
11948 }
11949 len = 0;
11950 do {
11951 len = strlen(ploopback->msg);
11952 if (len)
11953 break;
11954 rtw_msleep_os(1);
11955 } while (1);
11956 RTW_INFO("Free loopback, end the test.\n");
11957 _rtw_memcpy(pmsg, ploopback->msg, len + 1);
11958 freeLoopback(padapter);
11959
11960 return;
11961 }
11962
11963 /* disable dynamic algorithm */
11964 #ifndef CONFIG_NO_PHYDM
11965 rtw_phydm_ability_backup(padapter);
11966 rtw_phydm_func_disable_all(padapter);
11967 #endif
11968
11969 /* create pseudo ad-hoc connection */
11970 err = initpseudoadhoc(padapter);
11971 if (err == _FAIL) {
11972 sprintf(pmsg, "loopback FAIL! 1.1 init ad-hoc FAIL!");
11973 return;
11974 }
11975
11976 err = createpseudoadhoc(padapter);
11977 if (err == _FAIL) {
11978 sprintf(pmsg, "loopback FAIL! 1.2 create ad-hoc master FAIL!");
11979 return;
11980 }
11981
11982 err = initLoopback(padapter);
11983 if (err) {
11984 sprintf(pmsg, "loopback FAIL! 2. init FAIL! error code=%d", err);
11985 return;
11986 }
11987
11988 ploopback = padapter->ploopback;
11989
11990 ploopback->bstop = _FALSE;
11991 ploopback->cnt = cnt;
11992 ploopback->size = size;
11993 ploopback->lbkthread = kthread_run(lbk_thread, padapter, "RTW_LBK_THREAD");
11994 if (IS_ERR(ploopback->lbkthread)) {
11995 freeLoopback(padapter);
11996 ploopback->lbkthread = NULL;
11997 sprintf(pmsg, "loopback start FAIL! cnt=%d", cnt);
11998 return;
11999 }
12000
12001 sprintf(pmsg, "loopback start! cnt=%d", cnt);
12002 }
12003 #endif /* CONFIG_MAC_LOOPBACK_DRIVER */
12004
12005 static int rtw_test(
12006 struct net_device *dev,
12007 struct iw_request_info *info,
12008 union iwreq_data *wrqu, char *extra)
12009 {
12010 u32 len;
12011 u8 *pbuf, *pch;
12012 char *ptmp;
12013 u8 *delim = ",";
12014 PADAPTER padapter = rtw_netdev_priv(dev);
12015
12016
12017 RTW_INFO("+%s\n", __func__);
12018 len = wrqu->data.length;
12019
12020 pbuf = (u8 *)rtw_zmalloc(len + 1);
12021 if (pbuf == NULL) {
12022 RTW_INFO("%s: no memory!\n", __func__);
12023 return -ENOMEM;
12024 }
12025
12026 if (copy_from_user(pbuf, wrqu->data.pointer, len)) {
12027 rtw_mfree(pbuf, len + 1);
12028 RTW_INFO("%s: copy from user fail!\n", __func__);
12029 return -EFAULT;
12030 }
12031
12032 pbuf[len] = '\0';
12033
12034 RTW_INFO("%s: string=\"%s\"\n", __func__, pbuf);
12035
12036 ptmp = (char *)pbuf;
12037 pch = strsep(&ptmp, delim);
12038 if ((pch == NULL) || (strlen(pch) == 0)) {
12039 rtw_mfree(pbuf, len);
12040 RTW_INFO("%s: parameter error(level 1)!\n", __func__);
12041 return -EFAULT;
12042 }
12043
12044 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
12045 if (strcmp(pch, "init") == 0) {
12046 u8 status;
12047
12048 rtw_clr_drv_stopped(padapter); /* should clear drv_stopped, otherwise driver can't trx */
12049
12050 status = hal_init(padapter);
12051 RTW_INFO("HAL_INIT %s\n", status ? "SUCCESS" : "FAIL");
12052
12053 rtw_write8(padapter, REG_LOOPBACK_ENABLE, LOOKBACK_ENABLE_VALUE);
12054 RTW_INFO("Write 0x%03x to 0x%02x, enable loopback\n",
12055 REG_LOOPBACK_ENABLE, LOOKBACK_ENABLE_VALUE);
12056
12057 } else if (strcmp(pch, "loopback") == 0) {
12058 s32 cnt = 0;
12059 u32 size = 64;
12060
12061 pch = strsep(&ptmp, delim);
12062 if ((pch == NULL) || (strlen(pch) == 0)) {
12063 rtw_mfree(pbuf, len);
12064 RTW_INFO("%s: parameter error(level 2)!\n", __func__);
12065 return -EFAULT;
12066 }
12067
12068 sscanf(pch, "%d", &cnt);
12069 RTW_INFO("%s: loopback cnt=%d\n", __func__, cnt);
12070
12071 pch = strsep(&ptmp, delim);
12072 if ((pch == NULL) || (strlen(pch) == 0)) {
12073 rtw_mfree(pbuf, len);
12074 RTW_INFO("%s: parameter error(level 2)!\n", __func__);
12075 return -EFAULT;
12076 }
12077
12078 sscanf(pch, "%d", &size);
12079 RTW_INFO("%s: loopback size=%d\n", __func__, size);
12080
12081 loopbackTest(padapter, cnt, size, extra);
12082 wrqu->data.length = strlen(extra) + 1;
12083
12084 goto free_buf;
12085 }
12086 #endif
12087
12088
12089 #ifdef CONFIG_BT_COEXIST
12090 if (strcmp(pch, "bton") == 0) {
12091 rtw_btcoex_SetManualControl(padapter, _FALSE);
12092 goto free_buf;
12093 } else if (strcmp(pch, "btoff") == 0) {
12094 rtw_btcoex_SetManualControl(padapter, _TRUE);
12095 goto free_buf;
12096 } else if (strcmp(pch, "coex_auto") == 0) {
12097 rtw_btcoex_set_policy_control(padapter, BTCOEX_POLICY_CONTROL_AUTO);
12098 goto free_buf;
12099 } else if (strcmp(pch, "coex_force_freerun") == 0) {
12100 rtw_btcoex_set_policy_control(padapter, BTCOEX_POLICY_CONTROL_FORCE_FREERUN);
12101 goto free_buf;
12102 } else if (strcmp(pch, "coex_force_tdma") == 0) {
12103 rtw_btcoex_set_policy_control(padapter, BTCOEX_POLICY_CONTROL_FORCE_TDMA);
12104 goto free_buf;
12105 }
12106 #endif
12107
12108 if (strcmp(pch, "h2c") == 0) {
12109 u8 param[8];
12110 u8 count = 0;
12111 u32 tmp;
12112 u8 i;
12113 u32 pos;
12114 u8 ret;
12115
12116 do {
12117 pch = strsep(&ptmp, delim);
12118 if ((pch == NULL) || (strlen(pch) == 0))
12119 break;
12120
12121 sscanf(pch, "%x", &tmp);
12122 param[count++] = (u8)tmp;
12123 } while (count < 8);
12124
12125 if (count == 0) {
12126 rtw_mfree(pbuf, len);
12127 RTW_INFO("%s: parameter error(level 2)!\n", __func__);
12128 return -EFAULT;
12129 }
12130
12131 ret = rtw_test_h2c_cmd(padapter, param, count);
12132
12133 pos = sprintf(extra, "H2C ID=0x%02x content=", param[0]);
12134 for (i = 1; i < count; i++)
12135 pos += sprintf(extra + pos, "%02x,", param[i]);
12136 extra[pos] = 0;
12137 pos--;
12138 pos += sprintf(extra + pos, " %s", ret == _FAIL ? "FAIL" : "OK");
12139
12140 wrqu->data.length = strlen(extra) + 1;
12141
12142 goto free_buf;
12143 }
12144
12145 if (strcmp(pch, "dump_mac_reg") == 0) {
12146 mac_reg_dump(RTW_DBGDUMP, padapter);
12147 goto free_buf;
12148 }
12149
12150 free_buf:
12151 rtw_mfree(pbuf, len);
12152 return 0;
12153 }
12154
12155 static iw_handler rtw_handlers[] = {
12156 #ifdef CONFIG_IOCTL_WEXT
12157 NULL, /* SIOCSIWCOMMIT */
12158 rtw_wx_get_name, /* SIOCGIWNAME */
12159 dummy, /* SIOCSIWNWID */
12160 dummy, /* SIOCGIWNWID */
12161 rtw_wx_set_freq, /* SIOCSIWFREQ */
12162 rtw_wx_get_freq, /* SIOCGIWFREQ */
12163 rtw_wx_set_mode, /* SIOCSIWMODE */
12164 rtw_wx_get_mode, /* SIOCGIWMODE */
12165 dummy, /* SIOCSIWSENS */
12166 rtw_wx_get_sens, /* SIOCGIWSENS */
12167 NULL, /* SIOCSIWRANGE */
12168 rtw_wx_get_range, /* SIOCGIWRANGE */
12169 rtw_wx_set_priv, /* SIOCSIWPRIV */
12170 NULL, /* SIOCGIWPRIV */
12171 NULL, /* SIOCSIWSTATS */
12172 NULL, /* SIOCGIWSTATS */
12173 dummy, /* SIOCSIWSPY */
12174 dummy, /* SIOCGIWSPY */
12175 NULL, /* SIOCGIWTHRSPY */
12176 NULL, /* SIOCWIWTHRSPY */
12177 rtw_wx_set_wap, /* SIOCSIWAP */
12178 rtw_wx_get_wap, /* SIOCGIWAP */
12179 rtw_wx_set_mlme, /* request MLME operation; uses struct iw_mlme */
12180 dummy, /* SIOCGIWAPLIST -- depricated */
12181 rtw_wx_set_scan, /* SIOCSIWSCAN */
12182 rtw_wx_get_scan, /* SIOCGIWSCAN */
12183 rtw_wx_set_essid, /* SIOCSIWESSID */
12184 rtw_wx_get_essid, /* SIOCGIWESSID */
12185 dummy, /* SIOCSIWNICKN */
12186 rtw_wx_get_nick, /* SIOCGIWNICKN */
12187 NULL, /* -- hole -- */
12188 NULL, /* -- hole -- */
12189 rtw_wx_set_rate, /* SIOCSIWRATE */
12190 rtw_wx_get_rate, /* SIOCGIWRATE */
12191 rtw_wx_set_rts, /* SIOCSIWRTS */
12192 rtw_wx_get_rts, /* SIOCGIWRTS */
12193 rtw_wx_set_frag, /* SIOCSIWFRAG */
12194 rtw_wx_get_frag, /* SIOCGIWFRAG */
12195 dummy, /* SIOCSIWTXPOW */
12196 dummy, /* SIOCGIWTXPOW */
12197 dummy, /* SIOCSIWRETRY */
12198 rtw_wx_get_retry, /* SIOCGIWRETRY */
12199 rtw_wx_set_enc, /* SIOCSIWENCODE */
12200 rtw_wx_get_enc, /* SIOCGIWENCODE */
12201 dummy, /* SIOCSIWPOWER */
12202 rtw_wx_get_power, /* SIOCGIWPOWER */
12203 NULL, /*---hole---*/
12204 NULL, /*---hole---*/
12205 rtw_wx_set_gen_ie, /* SIOCSIWGENIE */
12206 NULL, /* SIOCGWGENIE */
12207 rtw_wx_set_auth, /* SIOCSIWAUTH */
12208 NULL, /* SIOCGIWAUTH */
12209 rtw_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
12210 NULL, /* SIOCGIWENCODEEXT */
12211 rtw_wx_set_pmkid, /* SIOCSIWPMKSA */
12212 NULL, /*---hole---*/
12213 #endif
12214 };
12215
12216
12217 static const struct iw_priv_args rtw_private_args[] = {
12218 {
12219 SIOCIWFIRSTPRIV + 0x0,
12220 IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write"
12221 },
12222 {
12223 SIOCIWFIRSTPRIV + 0x1,
12224 IW_PRIV_TYPE_CHAR | 0x7FF,
12225 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read"
12226 },
12227 {
12228 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
12229 },
12230 {
12231 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
12232 },
12233 {
12234 SIOCIWFIRSTPRIV + 0x4,
12235 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
12236 },
12237 {
12238 SIOCIWFIRSTPRIV + 0x5,
12239 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid"
12240 },
12241 {
12242 SIOCIWFIRSTPRIV + 0x6,
12243 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
12244 },
12245 /* for PLATFORM_MT53XX */
12246 {
12247 SIOCIWFIRSTPRIV + 0x7,
12248 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "get_sensitivity"
12249 },
12250 {
12251 SIOCIWFIRSTPRIV + 0x8,
12252 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_prob_req_ie"
12253 },
12254 {
12255 SIOCIWFIRSTPRIV + 0x9,
12256 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_assoc_req_ie"
12257 },
12258
12259 /* for RTK_DMP_PLATFORM */
12260 {
12261 SIOCIWFIRSTPRIV + 0xA,
12262 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan"
12263 },
12264
12265 {
12266 SIOCIWFIRSTPRIV + 0xB,
12267 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg"
12268 },
12269 {
12270 SIOCIWFIRSTPRIV + 0xC,
12271 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw"
12272 },
12273 {
12274 SIOCIWFIRSTPRIV + 0xD,
12275 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr"
12276 },
12277 #if 0
12278 {
12279 SIOCIWFIRSTPRIV + 0xE, 0, 0, "wowlan_ctrl"
12280 },
12281 #endif
12282 {
12283 SIOCIWFIRSTPRIV + 0x10,
12284 IW_PRIV_TYPE_CHAR | 1024, 0, "p2p_set"
12285 },
12286 {
12287 SIOCIWFIRSTPRIV + 0x11,
12288 IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK , "p2p_get"
12289 },
12290 {
12291 SIOCIWFIRSTPRIV + 0x12, 0, 0, "NULL"
12292 },
12293 {
12294 SIOCIWFIRSTPRIV + 0x13,
12295 IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64 , "p2p_get2"
12296 },
12297 {
12298 SIOCIWFIRSTPRIV + 0x14,
12299 IW_PRIV_TYPE_CHAR | 64, 0, "tdls"
12300 },
12301 {
12302 SIOCIWFIRSTPRIV + 0x15,
12303 IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024 , "tdls_get"
12304 },
12305 {
12306 SIOCIWFIRSTPRIV + 0x16,
12307 IW_PRIV_TYPE_CHAR | 64, 0, "pm_set"
12308 },
12309 #ifdef CONFIG_RTW_80211K
12310 {
12311 SIOCIWFIRSTPRIV + 0x17,
12312 IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024 , "rrm"
12313 },
12314 #else
12315 {SIOCIWFIRSTPRIV + 0x17, IW_PRIV_TYPE_CHAR | 1024 , 0 , "NULL"},
12316 #endif
12317 {SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ , 0 , "rereg_nd_name"},
12318 #ifdef CONFIG_MP_INCLUDED
12319 {SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0, "NULL"},
12320 {SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "NULL"},
12321 #else
12322 {SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0, "NULL"},
12323 {SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
12324 #endif
12325 {
12326 SIOCIWFIRSTPRIV + 0x1D,
12327 IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "test"
12328 },
12329
12330 { SIOCIWFIRSTPRIV + 0x0E, IW_PRIV_TYPE_CHAR | 1024, 0 , ""}, /* set */
12331 { SIOCIWFIRSTPRIV + 0x0F, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK , ""},/* get
12332 * --- sub-ioctls definitions --- */
12333
12334 #ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
12335 { VENDOR_IE_SET, IW_PRIV_TYPE_CHAR | 1024 , 0 , "vendor_ie_set" },
12336 { VENDOR_IE_GET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "vendor_ie_get" },
12337 #endif
12338 #if defined(CONFIG_RTL8723B)
12339 { MP_SetBT, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_setbt" },
12340 { MP_DISABLE_BT_COEXIST, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_disa_btcoex"},
12341 #endif
12342 #ifdef CONFIG_WOWLAN
12343 { MP_WOW_ENABLE , IW_PRIV_TYPE_CHAR | 1024, 0, "wow_mode" },
12344 { MP_WOW_SET_PATTERN , IW_PRIV_TYPE_CHAR | 1024, 0, "wow_set_pattern" },
12345 #endif
12346 #ifdef CONFIG_AP_WOWLAN
12347 { MP_AP_WOW_ENABLE , IW_PRIV_TYPE_CHAR | 1024, 0, "ap_wow_mode" }, /* set */
12348 #endif
12349 #ifdef CONFIG_SDIO_INDIRECT_ACCESS
12350 { MP_SD_IREAD, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "sd_iread" },
12351 { MP_SD_IWRITE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "sd_iwrite" },
12352 #endif
12353 };
12354
12355
12356 static const struct iw_priv_args rtw_mp_private_args[] = {
12357 /* --- sub-ioctls definitions --- */
12358 #ifdef CONFIG_MP_INCLUDED
12359 { MP_START , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_start" },
12360 { MP_PHYPARA, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_phypara" },
12361 { MP_STOP , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_stop" },
12362 { MP_CHANNEL , IW_PRIV_TYPE_CHAR | 1024 , IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_channel" },
12363 { MP_CHL_OFFSET , IW_PRIV_TYPE_CHAR | 1024 , IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ch_offset" },
12364 { MP_BANDWIDTH , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_bandwidth"},
12365 { MP_RATE , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate" },
12366 { MP_RESET_STATS , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_reset_stats"},
12367 { MP_QUERY , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK , "mp_query"},
12368 { READ_REG , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_reg" },
12369 { MP_RATE , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate" },
12370 { READ_RF , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_rf" },
12371 { MP_PSD , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_psd"},
12372 { MP_DUMP, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_dump" },
12373 { MP_TXPOWER , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_txpower"},
12374 { MP_ANT_TX , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_tx"},
12375 { MP_ANT_RX , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_rx"},
12376 { WRITE_REG , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_reg" },
12377 { WRITE_RF , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_rf" },
12378 { MP_CTX , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ctx"},
12379 { MP_ARX , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_arx"},
12380 { MP_THER , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ther"},
12381 { EFUSE_SET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_set" },
12382 { EFUSE_GET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get" },
12383 { MP_PWRTRK , IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_pwrtrk"},
12384 { MP_QueryDrvStats, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_drvquery" },
12385 { MP_IOCTL, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_ioctl"},
12386 { MP_SetRFPathSwh, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_setrfpath" },
12387 { MP_PwrCtlDM, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_pwrctldm" },
12388 { MP_GET_TXPOWER_INX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_get_txpower" },
12389 { MP_GETVER, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_priv_ver" },
12390 { MP_MON, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_mon" },
12391 { EFUSE_BT_MASK, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_bt_mask" },
12392 { EFUSE_MASK, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_mask" },
12393 { EFUSE_FILE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_file" },
12394 { EFUSE_FILE_STORE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_store" },
12395 { MP_TX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_tx" },
12396 { MP_RX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rx" },
12397 { MP_HW_TX_MODE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_hxtx" },
12398 { MP_PWRLMT, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_pwrlmt" },
12399 { MP_PWRBYRATE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_pwrbyrate" },
12400 { CTA_TEST, IW_PRIV_TYPE_CHAR | 1024, 0, "cta_test"},
12401 { MP_IQK, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_iqk"},
12402 { MP_LCK, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_lck"},
12403 { BT_EFUSE_FILE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "bt_efuse_file" },
12404 { MP_SWRFPath, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_swrfpath" },
12405 { MP_LINK, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_link" },
12406 { MP_DPK, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_dpk"},
12407 { MP_DPK_TRK, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_dpk_trk" },
12408 { MP_GET_TSSIDE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_get_tsside" },
12409 { MP_SET_TSSIDE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_set_tsside" },
12410 #ifdef CONFIG_RTW_CUSTOMER_STR
12411 { MP_CUSTOMER_STR, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "customer_str" },
12412 #endif
12413
12414 #endif /* CONFIG_MP_INCLUDED */
12415 };
12416
12417 static iw_handler rtw_private_handler[] = {
12418 rtw_wx_write32, /* 0x00 */
12419 rtw_wx_read32, /* 0x01 */
12420 NULL, /* 0x02 */
12421 #ifdef MP_IOCTL_HDL
12422 rtw_mp_ioctl_hdl, /* 0x03 */
12423 #else
12424 rtw_wx_priv_null,
12425 #endif
12426 /* for MM DTV platform */
12427 rtw_get_ap_info, /* 0x04 */
12428
12429 rtw_set_pid, /* 0x05 */
12430 rtw_wps_start, /* 0x06 */
12431
12432 /* for PLATFORM_MT53XX */
12433 rtw_wx_get_sensitivity, /* 0x07 */
12434 rtw_wx_set_mtk_wps_probe_ie, /* 0x08 */
12435 rtw_wx_set_mtk_wps_ie, /* 0x09 */
12436
12437 /* for RTK_DMP_PLATFORM
12438 * Set Channel depend on the country code */
12439 rtw_wx_set_channel_plan, /* 0x0A */
12440
12441 rtw_dbg_port, /* 0x0B */
12442 rtw_wx_write_rf, /* 0x0C */
12443 rtw_wx_read_rf, /* 0x0D */
12444
12445 rtw_priv_set, /*0x0E*/
12446 rtw_priv_get, /*0x0F*/
12447
12448 rtw_p2p_set, /* 0x10 */
12449 rtw_p2p_get, /* 0x11 */
12450 NULL, /* 0x12 */
12451 rtw_p2p_get2, /* 0x13 */
12452
12453 rtw_tdls, /* 0x14 */
12454 rtw_tdls_get, /* 0x15 */
12455
12456 rtw_pm_set, /* 0x16 */
12457 #ifdef CONFIG_RTW_80211K
12458 rtw_wx_priv_rrm, /* 0x17 */
12459 #else
12460 rtw_wx_priv_null, /* 0x17 */
12461 #endif
12462 rtw_rereg_nd_name, /* 0x18 */
12463 rtw_wx_priv_null, /* 0x19 */
12464 #ifdef CONFIG_MP_INCLUDED
12465 rtw_wx_priv_null, /* 0x1A */
12466 rtw_wx_priv_null, /* 0x1B */
12467 #else
12468 rtw_wx_priv_null, /* 0x1A */
12469 rtw_mp_efuse_get, /* 0x1B */
12470 #endif
12471 NULL, /* 0x1C is reserved for hostapd */
12472 rtw_test, /* 0x1D */
12473 };
12474
12475 #if WIRELESS_EXT >= 17
12476 static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
12477 {
12478 _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
12479 struct iw_statistics *piwstats = &padapter->iwstats;
12480 int tmp_level = 0;
12481 int tmp_qual = 0;
12482 int tmp_noise = 0;
12483
12484 if (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE) != _TRUE) {
12485 piwstats->qual.qual = 0;
12486 piwstats->qual.level = 0;
12487 piwstats->qual.noise = 0;
12488 /* RTW_INFO("No link level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise); */
12489 } else {
12490 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
12491 tmp_level = translate_percentage_to_dbm(padapter->recvpriv.signal_strength);
12492 #else
12493 tmp_level = padapter->recvpriv.signal_strength;
12494 #endif
12495
12496 tmp_qual = padapter->recvpriv.signal_qual;
12497 #ifdef CONFIG_BACKGROUND_NOISE_MONITOR
12498 if (IS_NM_ENABLE(padapter)) {
12499 tmp_noise = rtw_noise_measure_curchan(padapter);
12500 #ifndef CONFIG_SIGNAL_DISPLAY_DBM
12501 tmp_noise = translate_dbm_to_percentage(tmp_noise);/*percentage*/
12502 #endif
12503 }
12504 #endif
12505 /* RTW_INFO("level:%d, qual:%d, noise:%d, rssi (%d)\n", tmp_level, tmp_qual, tmp_noise,padapter->recvpriv.rssi); */
12506
12507 piwstats->qual.level = tmp_level;
12508 piwstats->qual.qual = tmp_qual;
12509 piwstats->qual.noise = tmp_noise;
12510 }
12511 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14))
12512 piwstats->qual.updated = IW_QUAL_ALL_UPDATED ;/* |IW_QUAL_DBM; */
12513 #else
12514 #ifdef RTK_DMP_PLATFORM
12515 /* IW_QUAL_DBM= 0x8, if driver use this flag, wireless extension will show value of dbm. */
12516 /* remove this flag for show percentage 0~100 */
12517 piwstats->qual.updated = 0x07;
12518 #else
12519 piwstats->qual.updated = 0x0f;
12520 #endif
12521 #endif
12522
12523 #ifdef CONFIG_SIGNAL_DISPLAY_DBM
12524 piwstats->qual.updated = piwstats->qual.updated | IW_QUAL_DBM;
12525 #endif
12526
12527 return &padapter->iwstats;
12528 }
12529 #endif
12530
12531 #ifdef CONFIG_WIRELESS_EXT
12532 struct iw_handler_def rtw_handlers_def = {
12533 .standard = rtw_handlers,
12534 .num_standard = sizeof(rtw_handlers) / sizeof(iw_handler),
12535 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)) || defined(CONFIG_WEXT_PRIV)
12536 .private = rtw_private_handler,
12537 .private_args = (struct iw_priv_args *)rtw_private_args,
12538 .num_private = sizeof(rtw_private_handler) / sizeof(iw_handler),
12539 .num_private_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args),
12540 #endif
12541 #if WIRELESS_EXT >= 17
12542 .get_wireless_stats = rtw_get_wireless_stats,
12543 #endif
12544 };
12545 #endif
12546
12547 /* copy from net/wireless/wext.c start
12548 * ----------------------------------------------------------------
12549 *
12550 * Calculate size of private arguments
12551 */
12552 static const char iw_priv_type_size[] = {
12553 0, /* IW_PRIV_TYPE_NONE */
12554 1, /* IW_PRIV_TYPE_BYTE */
12555 1, /* IW_PRIV_TYPE_CHAR */
12556 0, /* Not defined */
12557 sizeof(__u32), /* IW_PRIV_TYPE_INT */
12558 sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */
12559 sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */
12560 0, /* Not defined */
12561 };
12562
12563 static int get_priv_size(__u16 args)
12564 {
12565 int num = args & IW_PRIV_SIZE_MASK;
12566 int type = (args & IW_PRIV_TYPE_MASK) >> 12;
12567
12568 return num * iw_priv_type_size[type];
12569 }
12570 /* copy from net/wireless/wext.c end */
12571
12572
12573 static int _rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_data)
12574 {
12575 int err = 0;
12576 u8 *input = NULL;
12577 u32 input_len = 0;
12578 const char delim[] = " ";
12579 u8 *output = NULL;
12580 u32 output_len = 0;
12581 u32 count = 0;
12582 u8 *buffer = NULL;
12583 u32 buffer_len = 0;
12584 char *ptr = NULL;
12585 u8 cmdname[17] = {0}; /* IFNAMSIZ+1 */
12586 u32 cmdlen;
12587 s32 len;
12588 u8 *extra = NULL;
12589 u32 extra_size = 0;
12590
12591 s32 k;
12592 const iw_handler *priv; /* Private ioctl */
12593 const struct iw_priv_args *priv_args; /* Private ioctl description */
12594 const struct iw_priv_args *mp_priv_args; /*MP Private ioctl description */
12595 const struct iw_priv_args *sel_priv_args; /*Selected Private ioctl description */
12596 u32 num_priv; /* Number of ioctl */
12597 u32 num_priv_args; /* Number of descriptions */
12598 u32 num_mp_priv_args; /*Number of MP descriptions */
12599 u32 num_sel_priv_args; /*Number of Selected descriptions */
12600 iw_handler handler;
12601 int temp;
12602 int subcmd = 0; /* sub-ioctl index */
12603 int offset = 0; /* Space for sub-ioctl index */
12604
12605 union iwreq_data wdata;
12606
12607 _rtw_memcpy(&wdata, wrq_data, sizeof(wdata));
12608
12609 input_len = wdata.data.length;
12610 if (!input_len)
12611 return -EINVAL;
12612 input = rtw_zmalloc(input_len);
12613
12614 if (input == NULL) {
12615 err = -EOPNOTSUPP;
12616 goto exit;
12617 }
12618
12619 if (copy_from_user(input, wdata.data.pointer, input_len)) {
12620 err = -EFAULT;
12621 goto exit;
12622 }
12623 input[input_len - 1] = '\0';
12624 ptr = input;
12625 len = input_len;
12626
12627 sscanf(ptr, "%16s", cmdname);
12628 cmdlen = strlen(cmdname);
12629 RTW_DBG("%s: cmd=%s\n", __func__, cmdname);
12630
12631 /* skip command string */
12632 if (cmdlen > 0)
12633 cmdlen += 1; /* skip one space */
12634 ptr += cmdlen;
12635 len -= cmdlen;
12636 RTW_DBG("%s: parameters=%s\n", __func__, ptr);
12637
12638 priv = rtw_private_handler;
12639 priv_args = rtw_private_args;
12640 mp_priv_args = rtw_mp_private_args;
12641 num_priv = sizeof(rtw_private_handler) / sizeof(iw_handler);
12642 num_priv_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args);
12643 num_mp_priv_args = sizeof(rtw_mp_private_args) / sizeof(struct iw_priv_args);
12644
12645 if (num_priv_args == 0) {
12646 err = -EOPNOTSUPP;
12647 goto exit;
12648 }
12649
12650 /* Search the correct ioctl */
12651 k = -1;
12652 sel_priv_args = priv_args;
12653 num_sel_priv_args = num_priv_args;
12654 while
12655 ((++k < num_sel_priv_args) && strcmp(sel_priv_args[k].name, cmdname))
12656 ;
12657
12658 /* If not found... */
12659 if (k == num_sel_priv_args) {
12660 k = -1;
12661 sel_priv_args = mp_priv_args;
12662 num_sel_priv_args = num_mp_priv_args;
12663 while
12664 ((++k < num_sel_priv_args) && strcmp(sel_priv_args[k].name, cmdname))
12665 ;
12666
12667 if (k == num_sel_priv_args) {
12668 err = -EOPNOTSUPP;
12669 goto exit;
12670 }
12671 }
12672
12673 /* Watch out for sub-ioctls ! */
12674 if (sel_priv_args[k].cmd < SIOCDEVPRIVATE) {
12675 int j = -1;
12676
12677 /* Find the matching *real* ioctl */
12678 while ((++j < num_priv_args) && ((priv_args[j].name[0] != '\0') ||
12679 (priv_args[j].set_args != sel_priv_args[k].set_args) ||
12680 (priv_args[j].get_args != sel_priv_args[k].get_args)))
12681 ;
12682
12683 /* If not found... */
12684 if (j == num_priv_args) {
12685 err = -EINVAL;
12686 goto exit;
12687 }
12688
12689 /* Save sub-ioctl number */
12690 subcmd = sel_priv_args[k].cmd;
12691 /* Reserve one int (simplify alignment issues) */
12692 offset = sizeof(__u32);
12693 /* Use real ioctl definition from now on */
12694 k = j;
12695 }
12696
12697 buffer = rtw_zmalloc(4096);
12698 if (NULL == buffer) {
12699 err = -ENOMEM;
12700 goto exit;
12701 }
12702
12703 if (k >= num_priv_args) {
12704 err = -EINVAL;
12705 goto exit;
12706 }
12707
12708 /* If we have to set some data */
12709 if ((priv_args[k].set_args & IW_PRIV_TYPE_MASK) &&
12710 (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) {
12711 u8 *str;
12712
12713 switch (priv_args[k].set_args & IW_PRIV_TYPE_MASK) {
12714 case IW_PRIV_TYPE_BYTE:
12715 /* Fetch args */
12716 count = 0;
12717 do {
12718 str = strsep(&ptr, delim);
12719 if (NULL == str)
12720 break;
12721 sscanf(str, "%i", &temp);
12722 buffer[count++] = (u8)temp;
12723 } while (1);
12724 buffer_len = count;
12725
12726 /* Number of args to fetch */
12727 wdata.data.length = count;
12728 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
12729 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
12730
12731 break;
12732
12733 case IW_PRIV_TYPE_INT:
12734 /* Fetch args */
12735 count = 0;
12736 do {
12737 str = strsep(&ptr, delim);
12738 if (NULL == str)
12739 break;
12740 sscanf(str, "%i", &temp);
12741 ((s32 *)buffer)[count++] = (s32)temp;
12742 } while (1);
12743 buffer_len = count * sizeof(s32);
12744
12745 /* Number of args to fetch */
12746 wdata.data.length = count;
12747 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
12748 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
12749
12750 break;
12751
12752 case IW_PRIV_TYPE_CHAR:
12753 if (len > 0) {
12754 /* Size of the string to fetch */
12755 wdata.data.length = len;
12756 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
12757 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
12758
12759 /* Fetch string */
12760 _rtw_memcpy(buffer, ptr, wdata.data.length);
12761 } else {
12762 wdata.data.length = 1;
12763 buffer[0] = '\0';
12764 }
12765 buffer_len = wdata.data.length;
12766 break;
12767
12768 default:
12769 RTW_INFO("%s: Not yet implemented...\n", __func__);
12770 err = -1;
12771 goto exit;
12772 }
12773
12774 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
12775 (wdata.data.length != (priv_args[k].set_args & IW_PRIV_SIZE_MASK))) {
12776 RTW_INFO("%s: The command %s needs exactly %d argument(s)...\n",
12777 __func__, cmdname, priv_args[k].set_args & IW_PRIV_SIZE_MASK);
12778 err = -EINVAL;
12779 goto exit;
12780 }
12781 } /* if args to set */
12782 else
12783 wdata.data.length = 0L;
12784
12785 /* Those two tests are important. They define how the driver
12786 * will have to handle the data */
12787 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
12788 ((get_priv_size(priv_args[k].set_args) + offset) <= IFNAMSIZ)) {
12789 /* First case : all SET args fit within wrq */
12790 if (offset)
12791 wdata.mode = subcmd;
12792 _rtw_memcpy(wdata.name + offset, buffer, IFNAMSIZ - offset);
12793 } else {
12794 if ((priv_args[k].set_args == 0) &&
12795 (priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
12796 (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ)) {
12797 /* Second case : no SET args, GET args fit within wrq */
12798 if (offset)
12799 wdata.mode = subcmd;
12800 } else {
12801 /* Third case : args won't fit in wrq, or variable number of args */
12802 if (copy_to_user(wdata.data.pointer, buffer, buffer_len)) {
12803 err = -EFAULT;
12804 goto exit;
12805 }
12806 wdata.data.flags = subcmd;
12807 }
12808 }
12809
12810 rtw_mfree(input, input_len);
12811 input = NULL;
12812
12813 extra_size = 0;
12814 if (IW_IS_SET(priv_args[k].cmd)) {
12815 /* Size of set arguments */
12816 extra_size = get_priv_size(priv_args[k].set_args);
12817
12818 /* Does it fits in iwr ? */
12819 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
12820 ((extra_size + offset) <= IFNAMSIZ))
12821 extra_size = 0;
12822 } else {
12823 /* Size of get arguments */
12824 extra_size = get_priv_size(priv_args[k].get_args);
12825
12826 /* Does it fits in iwr ? */
12827 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
12828 (extra_size <= IFNAMSIZ))
12829 extra_size = 0;
12830 }
12831
12832 if (extra_size == 0) {
12833 extra = (u8 *)&wdata;
12834 rtw_mfree(buffer, 4096);
12835 buffer = NULL;
12836 } else
12837 extra = buffer;
12838
12839 handler = priv[priv_args[k].cmd - SIOCIWFIRSTPRIV];
12840 err = handler(dev, NULL, &wdata, extra);
12841
12842 /* If we have to get some data */
12843 if ((priv_args[k].get_args & IW_PRIV_TYPE_MASK) &&
12844 (priv_args[k].get_args & IW_PRIV_SIZE_MASK)) {
12845 int j;
12846 int n = 0; /* number of args */
12847 u8 str[20] = {0};
12848
12849 /* Check where is the returned data */
12850 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
12851 (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ))
12852 n = priv_args[k].get_args & IW_PRIV_SIZE_MASK;
12853 else
12854 n = wdata.data.length;
12855
12856 output = rtw_zmalloc(4096);
12857 if (NULL == output) {
12858 err = -ENOMEM;
12859 goto exit;
12860 }
12861
12862 switch (priv_args[k].get_args & IW_PRIV_TYPE_MASK) {
12863 case IW_PRIV_TYPE_BYTE:
12864 /* Display args */
12865 for (j = 0; j < n; j++) {
12866 sprintf(str, "%d ", extra[j]);
12867 len = strlen(str);
12868 output_len = strlen(output);
12869 if ((output_len + len + 1) > 4096) {
12870 err = -E2BIG;
12871 goto exit;
12872 }
12873 _rtw_memcpy(output + output_len, str, len);
12874 }
12875 break;
12876
12877 case IW_PRIV_TYPE_INT:
12878 /* Display args */
12879 for (j = 0; j < n; j++) {
12880 sprintf(str, "%d ", ((__s32 *)extra)[j]);
12881 len = strlen(str);
12882 output_len = strlen(output);
12883 if ((output_len + len + 1) > 4096) {
12884 err = -E2BIG;
12885 goto exit;
12886 }
12887 _rtw_memcpy(output + output_len, str, len);
12888 }
12889 break;
12890
12891 case IW_PRIV_TYPE_CHAR:
12892 /* Display args */
12893 _rtw_memcpy(output, extra, n);
12894 break;
12895
12896 default:
12897 RTW_INFO("%s: Not yet implemented...\n", __func__);
12898 err = -1;
12899 goto exit;
12900 }
12901
12902 output_len = strlen(output) + 1;
12903 wrq_data->data.length = output_len;
12904 if (copy_to_user(wrq_data->data.pointer, output, output_len)) {
12905 err = -EFAULT;
12906 goto exit;
12907 }
12908 } /* if args to set */
12909 else
12910 wrq_data->data.length = 0;
12911
12912 exit:
12913 if (input)
12914 rtw_mfree(input, input_len);
12915 if (buffer)
12916 rtw_mfree(buffer, 4096);
12917 if (output)
12918 rtw_mfree(output, 4096);
12919
12920 return err;
12921 }
12922
12923 #ifdef CONFIG_COMPAT
12924 static int rtw_ioctl_compat_wext_private(struct net_device *dev, struct ifreq *rq)
12925 {
12926 struct compat_iw_point iwp_compat;
12927 union iwreq_data wrq_data;
12928 int err = 0;
12929 RTW_DBG("%s:...\n", __func__);
12930 if (copy_from_user(&iwp_compat, rq->ifr_ifru.ifru_data, sizeof(struct compat_iw_point)))
12931 return -EFAULT;
12932
12933 wrq_data.data.pointer = compat_ptr(iwp_compat.pointer);
12934 wrq_data.data.length = iwp_compat.length;
12935 wrq_data.data.flags = iwp_compat.flags;
12936
12937 err = _rtw_ioctl_wext_private(dev, &wrq_data);
12938
12939 iwp_compat.pointer = ptr_to_compat(wrq_data.data.pointer);
12940 iwp_compat.length = wrq_data.data.length;
12941 iwp_compat.flags = wrq_data.data.flags;
12942 if (copy_to_user(rq->ifr_ifru.ifru_data, &iwp_compat, sizeof(struct compat_iw_point)))
12943 return -EFAULT;
12944
12945 return err;
12946 }
12947 #endif /* CONFIG_COMPAT */
12948
12949 static int rtw_ioctl_standard_wext_private(struct net_device *dev, struct ifreq *rq)
12950 {
12951 struct iw_point *iwp;
12952 union iwreq_data wrq_data;
12953 int err = 0;
12954 iwp = &wrq_data.data;
12955 RTW_DBG("%s:...\n", __func__);
12956 if (copy_from_user(iwp, rq->ifr_ifru.ifru_data, sizeof(struct iw_point)))
12957 return -EFAULT;
12958
12959 err = _rtw_ioctl_wext_private(dev, &wrq_data);
12960
12961 if (copy_to_user(rq->ifr_ifru.ifru_data, iwp, sizeof(struct iw_point)))
12962 return -EFAULT;
12963
12964 return err;
12965 }
12966
12967 static int rtw_ioctl_wext_private(struct net_device *dev, struct ifreq *rq)
12968 {
12969 #ifdef CONFIG_COMPAT
12970 #if (KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE)
12971 if (is_compat_task())
12972 #else
12973 if (in_compat_syscall())
12974 #endif
12975 return rtw_ioctl_compat_wext_private(dev, rq);
12976 else
12977 #endif /* CONFIG_COMPAT */
12978 return rtw_ioctl_standard_wext_private(dev, rq);
12979 }
12980
12981 int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
12982 {
12983 struct iwreq *wrq = (struct iwreq *)rq;
12984 int ret = 0;
12985
12986 switch (cmd) {
12987 #ifdef CONFIG_IOCTL_WEXT
12988 case RTL_IOCTL_WPA_SUPPLICANT:
12989 ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
12990 break;
12991 #ifdef CONFIG_AP_MODE
12992 case RTL_IOCTL_HOSTAPD:
12993 ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
12994 break;
12995 #ifdef CONFIG_WIRELESS_EXT
12996 case SIOCSIWMODE:
12997 ret = rtw_wx_set_mode(dev, NULL, &wrq->u, NULL);
12998 break;
12999 #endif
13000 #endif /* CONFIG_AP_MODE */
13001 #endif /* CONFIG_IOCTL_WEXT */
13002 case SIOCDEVPRIVATE:
13003 ret = rtw_ioctl_wext_private(dev, rq);
13004 break;
13005 case (SIOCDEVPRIVATE+1):
13006 ret = rtw_android_priv_cmd(dev, rq, cmd);
13007 break;
13008 default:
13009 ret = -EOPNOTSUPP;
13010 break;
13011 }
13012
13013 return ret;
13014 }
13015