staging: rtl8188eu: Remove rtw_is_list_empty(), wrapper for list_emty()
[deliverable/linux.git] / drivers / staging / rtl8188eu / os_dep / ioctl_linux.c
1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
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 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17 *
18 *
19 ******************************************************************************/
20 #define _IOCTL_LINUX_C_
21
22 #include <osdep_service.h>
23 #include <drv_types.h>
24 #include <wlan_bssdef.h>
25 #include <rtw_debug.h>
26 #include <wifi.h>
27 #include <rtw_mlme.h>
28 #include <rtw_mlme_ext.h>
29 #include <rtw_ioctl.h>
30 #include <rtw_ioctl_set.h>
31 #include <rtw_mp_ioctl.h>
32 #include <rtl8188e_hal.h>
33
34 #include <rtw_mp.h>
35 #include <rtw_iol.h>
36 #include <linux/vmalloc.h>
37
38 #define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30)
39
40 #define SCAN_ITEM_SIZE 768
41 #define MAX_CUSTOM_LEN 64
42 #define RATE_COUNT 4
43
44 /* combo scan */
45 #define WEXT_CSCAN_AMOUNT 9
46 #define WEXT_CSCAN_BUF_LEN 360
47 #define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00"
48 #define WEXT_CSCAN_HEADER_SIZE 12
49 #define WEXT_CSCAN_SSID_SECTION 'S'
50 #define WEXT_CSCAN_CHANNEL_SECTION 'C'
51 #define WEXT_CSCAN_NPROBE_SECTION 'N'
52 #define WEXT_CSCAN_ACTV_DWELL_SECTION 'A'
53 #define WEXT_CSCAN_PASV_DWELL_SECTION 'P'
54 #define WEXT_CSCAN_HOME_DWELL_SECTION 'H'
55 #define WEXT_CSCAN_TYPE_SECTION 'T'
56
57 static struct mp_ioctl_handler mp_ioctl_hdl[] = {
58 /*0*/ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_start_test_hdl, OID_RT_PRO_START_TEST)
59 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_stop_test_hdl, OID_RT_PRO_STOP_TEST)
60
61 GEN_HANDLER(sizeof(struct rwreg_param), rtl8188eu_oid_rt_pro_read_register_hdl, OID_RT_PRO_READ_REGISTER)
62 GEN_HANDLER(sizeof(struct rwreg_param), rtl8188eu_oid_rt_pro_write_register_hdl, OID_RT_PRO_WRITE_REGISTER)
63 GEN_HANDLER(sizeof(struct bb_reg_param), rtl8188eu_oid_rt_pro_read_bb_reg_hdl, OID_RT_PRO_READ_BB_REG)
64 /*5*/ GEN_HANDLER(sizeof(struct bb_reg_param), rtl8188eu_oid_rt_pro_write_bb_reg_hdl, OID_RT_PRO_WRITE_BB_REG)
65 GEN_HANDLER(sizeof(struct rf_reg_param), rtl8188eu_oid_rt_pro_read_rf_reg_hdl, OID_RT_PRO_RF_READ_REGISTRY)
66 GEN_HANDLER(sizeof(struct rf_reg_param), rtl8188eu_oid_rt_pro_write_rf_reg_hdl, OID_RT_PRO_RF_WRITE_REGISTRY)
67
68 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_channel_direct_call_hdl, OID_RT_PRO_SET_CHANNEL_DIRECT_CALL)
69 GEN_HANDLER(sizeof(struct txpower_param), rtl8188eu_oid_rt_pro_set_tx_power_control_hdl, OID_RT_PRO_SET_TX_POWER_CONTROL)
70 /*10*/ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_data_rate_hdl, OID_RT_PRO_SET_DATA_RATE)
71 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_set_bandwidth_hdl, OID_RT_SET_BANDWIDTH)
72 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_antenna_bb_hdl, OID_RT_PRO_SET_ANTENNA_BB)
73
74 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_continuous_tx_hdl, OID_RT_PRO_SET_CONTINUOUS_TX)
75 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_single_carrier_tx_hdl, OID_RT_PRO_SET_SINGLE_CARRIER_TX)
76 /*15*/ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_carrier_suppression_tx_hdl, OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX)
77 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_pro_set_single_tone_tx_hdl, OID_RT_PRO_SET_SINGLE_TONE_TX)
78
79 EXT_MP_IOCTL_HANDLER(0, xmit_packet, 0)
80
81 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_set_rx_packet_type_hdl, OID_RT_SET_RX_PACKET_TYPE)
82 GEN_HANDLER(0, rtl8188eu_oid_rt_reset_phy_rx_packet_count_hdl, OID_RT_RESET_PHY_RX_PACKET_COUNT)
83 /*20*/ GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_phy_rx_packet_received_hdl, OID_RT_GET_PHY_RX_PACKET_RECEIVED)
84 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_phy_rx_packet_crc32_error_hdl, OID_RT_GET_PHY_RX_PACKET_CRC32_ERROR)
85
86 GEN_HANDLER(sizeof(struct eeprom_rw_param), NULL, 0)
87 GEN_HANDLER(sizeof(struct eeprom_rw_param), NULL, 0)
88 GEN_HANDLER(sizeof(struct efuse_access_struct), rtl8188eu_oid_rt_pro_efuse_hdl, OID_RT_PRO_EFUSE)
89 /*25*/ GEN_HANDLER(0, rtl8188eu_oid_rt_pro_efuse_map_hdl, OID_RT_PRO_EFUSE_MAP)
90 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_efuse_max_size_hdl, OID_RT_GET_EFUSE_MAX_SIZE)
91 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_efuse_current_size_hdl, OID_RT_GET_EFUSE_CURRENT_SIZE)
92
93 GEN_HANDLER(sizeof(u32), rtl8188eu_oid_rt_get_thermal_meter_hdl, OID_RT_PRO_GET_THERMAL_METER)
94 GEN_HANDLER(sizeof(u8), rtl8188eu_oid_rt_pro_set_power_tracking_hdl, OID_RT_PRO_SET_POWER_TRACKING)
95 /*30*/ GEN_HANDLER(sizeof(u8), rtl8188eu_oid_rt_set_power_down_hdl, OID_RT_SET_POWER_DOWN)
96 /*31*/ GEN_HANDLER(0, rtl8188eu_oid_rt_pro_trigger_gpio_hdl, 0)
97 };
98
99 static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000,
100 6000000, 9000000, 12000000, 18000000, 24000000, 36000000,
101 48000000, 54000000};
102
103 static const char * const iw_operation_mode[] = {
104 "Auto", "Ad-Hoc", "Managed", "Master", "Repeater",
105 "Secondary", "Monitor"
106 };
107
108 static int hex2num_i(char c)
109 {
110 if (c >= '0' && c <= '9')
111 return c - '0';
112 if (c >= 'a' && c <= 'f')
113 return c - 'a' + 10;
114 if (c >= 'A' && c <= 'F')
115 return c - 'A' + 10;
116 return -1;
117 }
118
119 /**
120 * hwaddr_aton - Convert ASCII string to MAC address
121 * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
122 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
123 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
124 */
125 static int hwaddr_aton_i(const char *txt, u8 *addr)
126 {
127 int i;
128
129 for (i = 0; i < 6; i++) {
130 int a, b;
131
132 a = hex2num_i(*txt++);
133 if (a < 0)
134 return -1;
135 b = hex2num_i(*txt++);
136 if (b < 0)
137 return -1;
138 *addr++ = (a << 4) | b;
139 if (i < 5 && *txt++ != ':')
140 return -1;
141 }
142
143 return 0;
144 }
145
146 void indicate_wx_scan_complete_event(struct adapter *padapter)
147 {
148 union iwreq_data wrqu;
149
150 memset(&wrqu, 0, sizeof(union iwreq_data));
151 wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL);
152 }
153
154 void rtw_indicate_wx_assoc_event(struct adapter *padapter)
155 {
156 union iwreq_data wrqu;
157 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
158
159 memset(&wrqu, 0, sizeof(union iwreq_data));
160
161 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
162
163 memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
164
165 DBG_88E_LEVEL(_drv_always_, "assoc success\n");
166 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
167 }
168
169 void rtw_indicate_wx_disassoc_event(struct adapter *padapter)
170 {
171 union iwreq_data wrqu;
172
173 memset(&wrqu, 0, sizeof(union iwreq_data));
174
175 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
176 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
177
178 DBG_88E_LEVEL(_drv_always_, "indicate disassoc\n");
179 wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
180 }
181
182 static char *translate_scan(struct adapter *padapter,
183 struct iw_request_info *info,
184 struct wlan_network *pnetwork,
185 char *start, char *stop)
186 {
187 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
188 struct iw_event iwe;
189 u16 cap;
190 __le16 le_tmp;
191 u32 ht_ielen = 0;
192 char custom[MAX_CUSTOM_LEN];
193 char *p;
194 u16 max_rate = 0, rate, ht_cap = false;
195 u32 i = 0;
196 u8 bw_40MHz = 0, short_GI = 0;
197 u16 mcs_rate = 0;
198 u8 ss, sq;
199 #ifdef CONFIG_88EU_P2P
200 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
201
202 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
203 u32 blnGotP2PIE = false;
204
205 /* User is doing the P2P device discovery */
206 /* The prefix of SSID should be "DIRECT-" and the IE should contains the P2P IE. */
207 /* If not, the driver should ignore this AP and go to the next AP. */
208
209 /* Verifying the SSID */
210 if (!memcmp(pnetwork->network.Ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN)) {
211 u32 p2pielen = 0;
212
213 if (pnetwork->network.Reserved[0] == 2) {/* Probe Request */
214 /* Verifying the P2P IE */
215 if (rtw_get_p2p_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &p2pielen))
216 blnGotP2PIE = true;
217 } else {/* Beacon or Probe Respones */
218 /* Verifying the P2P IE */
219 if (rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen))
220 blnGotP2PIE = true;
221 }
222 }
223
224 if (!blnGotP2PIE)
225 return start;
226 }
227 #endif /* CONFIG_88EU_P2P */
228
229 /* AP MAC address */
230 iwe.cmd = SIOCGIWAP;
231 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
232
233 memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
234 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
235
236 /* Add the ESSID */
237 iwe.cmd = SIOCGIWESSID;
238 iwe.u.data.flags = 1;
239 iwe.u.data.length = min_t(u16, pnetwork->network.Ssid.SsidLength, 32);
240 start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
241
242 /* parsing HT_CAP_IE */
243 p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength-12);
244
245 if (p && ht_ielen > 0) {
246 struct rtw_ieee80211_ht_cap *pht_capie;
247 ht_cap = true;
248 pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2);
249 memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
250 bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
251 short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
252 }
253
254 /* Add the protocol name */
255 iwe.cmd = SIOCGIWNAME;
256 if ((rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates))) {
257 if (ht_cap)
258 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
259 else
260 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
261 } else if ((rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates))) {
262 if (ht_cap)
263 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
264 else
265 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
266 } else {
267 if (pnetwork->network.Configuration.DSConfig > 14) {
268 if (ht_cap)
269 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11an");
270 else
271 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
272 } else {
273 if (ht_cap)
274 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
275 else
276 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
277 }
278 }
279
280 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
281
282 /* Add mode */
283 iwe.cmd = SIOCGIWMODE;
284 memcpy(&le_tmp, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
285
286 cap = le16_to_cpu(le_tmp);
287
288 if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
289 if (cap & WLAN_CAPABILITY_BSS)
290 iwe.u.mode = IW_MODE_MASTER;
291 else
292 iwe.u.mode = IW_MODE_ADHOC;
293
294 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
295 }
296
297 if (pnetwork->network.Configuration.DSConfig < 1)
298 pnetwork->network.Configuration.DSConfig = 1;
299
300 /* Add frequency/channel */
301 iwe.cmd = SIOCGIWFREQ;
302 iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
303 iwe.u.freq.e = 1;
304 iwe.u.freq.i = pnetwork->network.Configuration.DSConfig;
305 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
306
307 /* Add encryption capability */
308 iwe.cmd = SIOCGIWENCODE;
309 if (cap & WLAN_CAPABILITY_PRIVACY)
310 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
311 else
312 iwe.u.data.flags = IW_ENCODE_DISABLED;
313 iwe.u.data.length = 0;
314 start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
315
316 /*Add basic and extended rates */
317 max_rate = 0;
318 p = custom;
319 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
320 while (pnetwork->network.SupportedRates[i] != 0) {
321 rate = pnetwork->network.SupportedRates[i]&0x7F;
322 if (rate > max_rate)
323 max_rate = rate;
324 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
325 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
326 i++;
327 }
328
329 if (ht_cap) {
330 if (mcs_rate&0x8000)/* MCS15 */
331 max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130);
332 else if (mcs_rate&0x0080)/* MCS7 */
333 ;
334 else/* default MCS7 */
335 max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65);
336
337 max_rate = max_rate*2;/* Mbps/2; */
338 }
339
340 iwe.cmd = SIOCGIWRATE;
341 iwe.u.bitrate.fixed = 0;
342 iwe.u.bitrate.disabled = 0;
343 iwe.u.bitrate.value = max_rate * 500000;
344 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
345
346 /* parsing WPA/WPA2 IE */
347 {
348 u8 buf[MAX_WPA_IE_LEN];
349 u8 wpa_ie[255], rsn_ie[255];
350 u16 wpa_len = 0, rsn_len = 0;
351 u8 *p;
352
353 rtw_get_sec_ie(pnetwork->network.IEs, pnetwork->network.IELength, rsn_ie, &rsn_len, wpa_ie, &wpa_len);
354 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid =%s\n", pnetwork->network.Ssid.Ssid));
355 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len));
356
357 if (wpa_len > 0) {
358 p = buf;
359 memset(buf, 0, MAX_WPA_IE_LEN);
360 p += sprintf(p, "wpa_ie=");
361 for (i = 0; i < wpa_len; i++)
362 p += sprintf(p, "%02x", wpa_ie[i]);
363
364 memset(&iwe, 0, sizeof(iwe));
365 iwe.cmd = IWEVCUSTOM;
366 iwe.u.data.length = strlen(buf);
367 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
368
369 memset(&iwe, 0, sizeof(iwe));
370 iwe.cmd = IWEVGENIE;
371 iwe.u.data.length = wpa_len;
372 start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie);
373 }
374 if (rsn_len > 0) {
375 p = buf;
376 memset(buf, 0, MAX_WPA_IE_LEN);
377 p += sprintf(p, "rsn_ie=");
378 for (i = 0; i < rsn_len; i++)
379 p += sprintf(p, "%02x", rsn_ie[i]);
380 memset(&iwe, 0, sizeof(iwe));
381 iwe.cmd = IWEVCUSTOM;
382 iwe.u.data.length = strlen(buf);
383 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
384
385 memset(&iwe, 0, sizeof(iwe));
386 iwe.cmd = IWEVGENIE;
387 iwe.u.data.length = rsn_len;
388 start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie);
389 }
390 }
391
392 {/* parsing WPS IE */
393 uint cnt = 0, total_ielen;
394 u8 *wpsie_ptr = NULL;
395 uint wps_ielen = 0;
396
397 u8 *ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
398 total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
399
400 while (cnt < total_ielen) {
401 if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) {
402 wpsie_ptr = &ie_ptr[cnt];
403 iwe.cmd = IWEVGENIE;
404 iwe.u.data.length = (u16)wps_ielen;
405 start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr);
406 }
407 cnt += ie_ptr[cnt+1]+2; /* goto next */
408 }
409 }
410
411 /* Add quality statistics */
412 iwe.cmd = IWEVQUAL;
413 iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID;
414
415 if (check_fwstate(pmlmepriv, _FW_LINKED) == true &&
416 is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network)) {
417 ss = padapter->recvpriv.signal_strength;
418 sq = padapter->recvpriv.signal_qual;
419 } else {
420 ss = pnetwork->network.PhyInfo.SignalStrength;
421 sq = pnetwork->network.PhyInfo.SignalQuality;
422 }
423
424 iwe.u.qual.level = (u8)ss;
425 iwe.u.qual.qual = (u8)sq; /* signal quality */
426 iwe.u.qual.noise = 0; /* noise level */
427 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
428 return start;
429 }
430
431 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
432 {
433 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
434 int ret = 0;
435
436 if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
437 DBG_88E("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY and AUTH_ALG_OPEN_SYSTEM [value:0x%x]\n", value);
438 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
439 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
440 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
441 } else if (value & AUTH_ALG_SHARED_KEY) {
442 DBG_88E("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY [value:0x%x]\n", value);
443 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
444
445 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
446 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
447 } else if (value & AUTH_ALG_OPEN_SYSTEM) {
448 DBG_88E("wpa_set_auth_algs, AUTH_ALG_OPEN_SYSTEM\n");
449 if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
450 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
451 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
452 }
453 } else if (value & AUTH_ALG_LEAP) {
454 DBG_88E("wpa_set_auth_algs, AUTH_ALG_LEAP\n");
455 } else {
456 DBG_88E("wpa_set_auth_algs, error!\n");
457 ret = -EINVAL;
458 }
459 return ret;
460 }
461
462 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
463 {
464 int ret = 0;
465 u32 wep_key_idx, wep_key_len, wep_total_len;
466 struct ndis_802_11_wep *pwep = NULL;
467 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
468 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
469 struct security_priv *psecuritypriv = &padapter->securitypriv;
470 #ifdef CONFIG_88EU_P2P
471 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
472 #endif /* CONFIG_88EU_P2P */
473
474 param->u.crypt.err = 0;
475 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
476
477 if (param_len < (u32) ((u8 *)param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) {
478 ret = -EINVAL;
479 goto exit;
480 }
481
482 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
483 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
484 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
485 if (param->u.crypt.idx >= WEP_KEYS) {
486 ret = -EINVAL;
487 goto exit;
488 }
489 } else {
490 ret = -EINVAL;
491 goto exit;
492 }
493
494 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
495 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("wpa_set_encryption, crypt.alg = WEP\n"));
496 DBG_88E("wpa_set_encryption, crypt.alg = WEP\n");
497
498 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
499 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
500 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
501
502 wep_key_idx = param->u.crypt.idx;
503 wep_key_len = param->u.crypt.key_len;
504
505 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(1)wep_key_idx =%d\n", wep_key_idx));
506 DBG_88E("(1)wep_key_idx =%d\n", wep_key_idx);
507
508 if (wep_key_idx > WEP_KEYS)
509 return -EINVAL;
510
511 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(2)wep_key_idx =%d\n", wep_key_idx));
512
513 if (wep_key_len > 0) {
514 wep_key_len = wep_key_len <= 5 ? 5 : 13;
515 wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
516 pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
517 if (pwep == NULL) {
518 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, (" wpa_set_encryption: pwep allocate fail !!!\n"));
519 goto exit;
520 }
521 memset(pwep, 0, wep_total_len);
522 pwep->KeyLength = wep_key_len;
523 pwep->Length = wep_total_len;
524 if (wep_key_len == 13) {
525 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
526 padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
527 }
528 } else {
529 ret = -EINVAL;
530 goto exit;
531 }
532 pwep->KeyIndex = wep_key_idx;
533 pwep->KeyIndex |= 0x80000000;
534 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
535 if (param->u.crypt.set_tx) {
536 DBG_88E("wep, set_tx = 1\n");
537 if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
538 ret = -EOPNOTSUPP;
539 } else {
540 DBG_88E("wep, set_tx = 0\n");
541 if (wep_key_idx >= WEP_KEYS) {
542 ret = -EOPNOTSUPP;
543 goto exit;
544 }
545 memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
546 psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
547 rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0);
548 }
549 goto exit;
550 }
551
552 if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /* 802_1x */
553 struct sta_info *psta, *pbcmc_sta;
554 struct sta_priv *pstapriv = &padapter->stapriv;
555
556 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE)) { /* sta mode */
557 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
558 if (psta == NULL) {
559 ;
560 } else {
561 if (strcmp(param->u.crypt.alg, "none") != 0)
562 psta->ieee8021x_blocked = false;
563
564 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
565 (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
566 psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
567
568 if (param->u.crypt.set_tx == 1) { /* pairwise key */
569 memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
570
571 if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
572 memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
573 memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
574 padapter->securitypriv.busetkipkey = false;
575 }
576
577 DBG_88E(" ~~~~set sta key:unicastkey\n");
578
579 rtw_setstakey_cmd(padapter, (unsigned char *)psta, true);
580 } else { /* group key */
581 memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
582 memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
583 memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
584 padapter->securitypriv.binstallGrpkey = true;
585 DBG_88E(" ~~~~set sta key:groupkey\n");
586
587 padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
588
589 rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1);
590 #ifdef CONFIG_88EU_P2P
591 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
592 rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_DONE);
593 #endif /* CONFIG_88EU_P2P */
594 }
595 }
596 pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
597 if (pbcmc_sta == NULL) {
598 ;
599 } else {
600 /* Jeff: don't disable ieee8021x_blocked while clearing key */
601 if (strcmp(param->u.crypt.alg, "none") != 0)
602 pbcmc_sta->ieee8021x_blocked = false;
603
604 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
605 (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
606 pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
607 }
608 }
609 }
610
611 exit:
612
613 kfree(pwep);
614 return ret;
615 }
616
617 static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen)
618 {
619 u8 *buf = NULL;
620 int group_cipher = 0, pairwise_cipher = 0;
621 int ret = 0;
622 #ifdef CONFIG_88EU_P2P
623 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
624 #endif /* CONFIG_88EU_P2P */
625
626 if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) {
627 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
628 if (pie == NULL)
629 return ret;
630 else
631 return -EINVAL;
632 }
633
634 if (ielen) {
635 buf = rtw_zmalloc(ielen);
636 if (buf == NULL) {
637 ret = -ENOMEM;
638 goto exit;
639 }
640
641 memcpy(buf, pie, ielen);
642
643 /* dump */
644 {
645 int i;
646 DBG_88E("\n wpa_ie(length:%d):\n", ielen);
647 for (i = 0; i < ielen; i += 8)
648 DBG_88E("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]);
649 }
650
651 if (ielen < RSN_HEADER_LEN) {
652 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("Ie len too short %d\n", ielen));
653 ret = -1;
654 goto exit;
655 }
656
657 if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
658 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
659 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
660 memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
661 }
662
663 if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
664 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
665 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
666 memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
667 }
668
669 switch (group_cipher) {
670 case WPA_CIPHER_NONE:
671 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
672 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
673 break;
674 case WPA_CIPHER_WEP40:
675 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
676 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
677 break;
678 case WPA_CIPHER_TKIP:
679 padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
680 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
681 break;
682 case WPA_CIPHER_CCMP:
683 padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
684 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
685 break;
686 case WPA_CIPHER_WEP104:
687 padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
688 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
689 break;
690 }
691
692 switch (pairwise_cipher) {
693 case WPA_CIPHER_NONE:
694 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
695 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
696 break;
697 case WPA_CIPHER_WEP40:
698 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
699 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
700 break;
701 case WPA_CIPHER_TKIP:
702 padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
703 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
704 break;
705 case WPA_CIPHER_CCMP:
706 padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
707 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
708 break;
709 case WPA_CIPHER_WEP104:
710 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
711 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
712 break;
713 }
714
715 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
716 {/* set wps_ie */
717 u16 cnt = 0;
718 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
719
720 while (cnt < ielen) {
721 eid = buf[cnt];
722 if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&buf[cnt+2], wps_oui, 4))) {
723 DBG_88E("SET WPS_IE\n");
724
725 padapter->securitypriv.wps_ie_len = ((buf[cnt+1]+2) < (MAX_WPA_IE_LEN<<2)) ? (buf[cnt+1]+2) : (MAX_WPA_IE_LEN<<2);
726
727 memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
728
729 set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
730 #ifdef CONFIG_88EU_P2P
731 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK))
732 rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_ING);
733 #endif /* CONFIG_88EU_P2P */
734 cnt += buf[cnt+1]+2;
735 break;
736 } else {
737 cnt += buf[cnt+1]+2; /* goto next */
738 }
739 }
740 }
741 }
742
743 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
744 ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->securitypriv.ndisencryptstatus =%d padapter->securitypriv.ndisauthtype =%d\n",
745 pairwise_cipher, padapter->securitypriv.ndisencryptstatus, padapter->securitypriv.ndisauthtype));
746 exit:
747 kfree(buf);
748 return ret;
749 }
750
751 typedef unsigned char NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX];
752
753 static int rtw_wx_get_name(struct net_device *dev,
754 struct iw_request_info *info,
755 union iwreq_data *wrqu, char *extra)
756 {
757 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
758 u32 ht_ielen = 0;
759 char *p;
760 u8 ht_cap = false;
761 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
762 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
763 NDIS_802_11_RATES_EX *prates = NULL;
764
765 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("cmd_code =%x\n", info->cmd));
766
767 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) {
768 /* parsing HT_CAP_IE */
769 p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength-12);
770 if (p && ht_ielen > 0)
771 ht_cap = true;
772
773 prates = &pcur_bss->SupportedRates;
774
775 if (rtw_is_cckratesonly_included((u8 *)prates) == true) {
776 if (ht_cap)
777 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
778 else
779 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
780 } else if ((rtw_is_cckrates_included((u8 *)prates)) == true) {
781 if (ht_cap)
782 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
783 else
784 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
785 } else {
786 if (pcur_bss->Configuration.DSConfig > 14) {
787 if (ht_cap)
788 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an");
789 else
790 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a");
791 } else {
792 if (ht_cap)
793 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
794 else
795 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
796 }
797 }
798 } else {
799 snprintf(wrqu->name, IFNAMSIZ, "unassociated");
800 }
801 return 0;
802 }
803
804 static int rtw_wx_set_freq(struct net_device *dev,
805 struct iw_request_info *info,
806 union iwreq_data *wrqu, char *extra)
807 {
808 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_wx_set_freq\n"));
809 return 0;
810 }
811
812 static int rtw_wx_get_freq(struct net_device *dev,
813 struct iw_request_info *info,
814 union iwreq_data *wrqu, char *extra)
815 {
816 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
817 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
818 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
819
820 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
821 /* wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000; */
822 wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
823 wrqu->freq.e = 1;
824 wrqu->freq.i = pcur_bss->Configuration.DSConfig;
825 } else {
826 wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
827 wrqu->freq.e = 1;
828 wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
829 }
830
831 return 0;
832 }
833
834 static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
835 union iwreq_data *wrqu, char *b)
836 {
837 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
838 enum ndis_802_11_network_infra networkType;
839 int ret = 0;
840
841 if (_FAIL == rtw_pwr_wakeup(padapter)) {
842 ret = -EPERM;
843 goto exit;
844 }
845
846 if (!padapter->hw_init_completed) {
847 ret = -EPERM;
848 goto exit;
849 }
850
851 switch (wrqu->mode) {
852 case IW_MODE_AUTO:
853 networkType = Ndis802_11AutoUnknown;
854 DBG_88E("set_mode = IW_MODE_AUTO\n");
855 break;
856 case IW_MODE_ADHOC:
857 networkType = Ndis802_11IBSS;
858 DBG_88E("set_mode = IW_MODE_ADHOC\n");
859 break;
860 case IW_MODE_MASTER:
861 networkType = Ndis802_11APMode;
862 DBG_88E("set_mode = IW_MODE_MASTER\n");
863 break;
864 case IW_MODE_INFRA:
865 networkType = Ndis802_11Infrastructure;
866 DBG_88E("set_mode = IW_MODE_INFRA\n");
867 break;
868 default:
869 ret = -EINVAL;
870 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("\n Mode: %s is not supported\n", iw_operation_mode[wrqu->mode]));
871 goto exit;
872 }
873 if (rtw_set_802_11_infrastructure_mode(padapter, networkType) == false) {
874 ret = -EPERM;
875 goto exit;
876 }
877 rtw_setopmode_cmd(padapter, networkType);
878 exit:
879 return ret;
880 }
881
882 static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
883 union iwreq_data *wrqu, char *b)
884 {
885 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
886 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
887
888 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_get_mode\n"));
889
890 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
891 wrqu->mode = IW_MODE_INFRA;
892 else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
893 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
894 wrqu->mode = IW_MODE_ADHOC;
895 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
896 wrqu->mode = IW_MODE_MASTER;
897 else
898 wrqu->mode = IW_MODE_AUTO;
899
900 return 0;
901 }
902
903 static int rtw_wx_set_pmkid(struct net_device *dev,
904 struct iw_request_info *a,
905 union iwreq_data *wrqu, char *extra)
906 {
907 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
908 u8 j, blInserted = false;
909 int ret = false;
910 struct security_priv *psecuritypriv = &padapter->securitypriv;
911 struct iw_pmksa *pPMK = (struct iw_pmksa *)extra;
912 u8 strZeroMacAddress[ETH_ALEN] = {0x00};
913 u8 strIssueBssid[ETH_ALEN] = {0x00};
914
915 memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
916 if (pPMK->cmd == IW_PMKSA_ADD) {
917 DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n");
918 if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
919 return ret;
920 else
921 ret = true;
922 blInserted = false;
923
924 /* overwrite PMKID */
925 for (j = 0; j < NUM_PMKID_CACHE; j++) {
926 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
927 /* BSSID is matched, the same AP => rewrite with new PMKID. */
928 DBG_88E("[rtw_wx_set_pmkid] BSSID exists in the PMKList.\n");
929 memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
930 psecuritypriv->PMKIDList[j].bUsed = true;
931 psecuritypriv->PMKIDIndex = j+1;
932 blInserted = true;
933 break;
934 }
935 }
936
937 if (!blInserted) {
938 /* Find a new entry */
939 DBG_88E("[rtw_wx_set_pmkid] Use the new entry index = %d for this PMKID.\n",
940 psecuritypriv->PMKIDIndex);
941
942 memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
943 memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
944
945 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = true;
946 psecuritypriv->PMKIDIndex++;
947 if (psecuritypriv->PMKIDIndex == 16)
948 psecuritypriv->PMKIDIndex = 0;
949 }
950 } else if (pPMK->cmd == IW_PMKSA_REMOVE) {
951 DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_REMOVE!\n");
952 ret = true;
953 for (j = 0; j < NUM_PMKID_CACHE; j++) {
954 if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
955 /* BSSID is matched, the same AP => Remove this PMKID information and reset it. */
956 memset(psecuritypriv->PMKIDList[j].Bssid, 0x00, ETH_ALEN);
957 psecuritypriv->PMKIDList[j].bUsed = false;
958 break;
959 }
960 }
961 } else if (pPMK->cmd == IW_PMKSA_FLUSH) {
962 DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n");
963 memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
964 psecuritypriv->PMKIDIndex = 0;
965 ret = true;
966 }
967 return ret;
968 }
969
970 static int rtw_wx_get_sens(struct net_device *dev,
971 struct iw_request_info *info,
972 union iwreq_data *wrqu, char *extra)
973 {
974 wrqu->sens.value = 0;
975 wrqu->sens.fixed = 0; /* no auto select */
976 wrqu->sens.disabled = 1;
977 return 0;
978 }
979
980 static int rtw_wx_get_range(struct net_device *dev,
981 struct iw_request_info *info,
982 union iwreq_data *wrqu, char *extra)
983 {
984 struct iw_range *range = (struct iw_range *)extra;
985 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
986 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
987
988 u16 val;
989 int i;
990
991 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_range. cmd_code =%x\n", info->cmd));
992
993 wrqu->data.length = sizeof(*range);
994 memset(range, 0, sizeof(*range));
995
996 /* Let's try to keep this struct in the same order as in
997 * linux/include/wireless.h
998 */
999
1000 /* TODO: See what values we can set, and remove the ones we can't
1001 * set, or fill them with some default data.
1002 */
1003
1004 /* ~5 Mb/s real (802.11b) */
1005 range->throughput = 5 * 1000 * 1000;
1006
1007 /* signal level threshold range */
1008
1009 /* percent values between 0 and 100. */
1010 range->max_qual.qual = 100;
1011 range->max_qual.level = 100;
1012 range->max_qual.noise = 100;
1013 range->max_qual.updated = 7; /* Updated all three */
1014
1015 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
1016 /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
1017 range->avg_qual.level = 178; /* -78 dBm */
1018 range->avg_qual.noise = 0;
1019 range->avg_qual.updated = 7; /* Updated all three */
1020
1021 range->num_bitrates = RATE_COUNT;
1022
1023 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
1024 range->bitrate[i] = rtw_rates[i];
1025
1026 range->min_frag = MIN_FRAG_THRESHOLD;
1027 range->max_frag = MAX_FRAG_THRESHOLD;
1028
1029 range->pm_capa = 0;
1030
1031 range->we_version_compiled = WIRELESS_EXT;
1032 range->we_version_source = 16;
1033
1034 for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
1035 /* Include only legal frequencies for some countries */
1036 if (pmlmeext->channel_set[i].ChannelNum != 0) {
1037 range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
1038 range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
1039 range->freq[val].e = 1;
1040 val++;
1041 }
1042
1043 if (val == IW_MAX_FREQUENCIES)
1044 break;
1045 }
1046
1047 range->num_channels = val;
1048 range->num_frequency = val;
1049
1050 /* The following code will proivde the security capability to network manager. */
1051 /* If the driver doesn't provide this capability to network manager, */
1052 /* the WPA/WPA2 routers can't be chosen in the network manager. */
1053
1054 /*
1055 #define IW_SCAN_CAPA_NONE 0x00
1056 #define IW_SCAN_CAPA_ESSID 0x01
1057 #define IW_SCAN_CAPA_BSSID 0x02
1058 #define IW_SCAN_CAPA_CHANNEL 0x04
1059 #define IW_SCAN_CAPA_MODE 0x08
1060 #define IW_SCAN_CAPA_RATE 0x10
1061 #define IW_SCAN_CAPA_TYPE 0x20
1062 #define IW_SCAN_CAPA_TIME 0x40
1063 */
1064
1065 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
1066 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
1067
1068 range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE |
1069 IW_SCAN_CAPA_BSSID | IW_SCAN_CAPA_CHANNEL |
1070 IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE;
1071 return 0;
1072 }
1073
1074 /* set bssid flow */
1075 /* s1. rtw_set_802_11_infrastructure_mode() */
1076 /* s2. rtw_set_802_11_authentication_mode() */
1077 /* s3. set_802_11_encryption_mode() */
1078 /* s4. rtw_set_802_11_bssid() */
1079 static int rtw_wx_set_wap(struct net_device *dev,
1080 struct iw_request_info *info,
1081 union iwreq_data *awrq,
1082 char *extra)
1083 {
1084 uint ret = 0;
1085 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1086 struct sockaddr *temp = (struct sockaddr *)awrq;
1087 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1088 struct list_head *phead;
1089 u8 *dst_bssid, *src_bssid;
1090 struct __queue *queue = &(pmlmepriv->scanned_queue);
1091 struct wlan_network *pnetwork = NULL;
1092 enum ndis_802_11_auth_mode authmode;
1093
1094 if (_FAIL == rtw_pwr_wakeup(padapter)) {
1095 ret = -1;
1096 goto exit;
1097 }
1098
1099 if (!padapter->bup) {
1100 ret = -1;
1101 goto exit;
1102 }
1103
1104 if (temp->sa_family != ARPHRD_ETHER) {
1105 ret = -EINVAL;
1106 goto exit;
1107 }
1108
1109 authmode = padapter->securitypriv.ndisauthtype;
1110 spin_lock_bh(&queue->lock);
1111 phead = get_list_head(queue);
1112 pmlmepriv->pscanned = phead->next;
1113
1114 while (phead != pmlmepriv->pscanned) {
1115 pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
1116
1117 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1118
1119 dst_bssid = pnetwork->network.MacAddress;
1120
1121 src_bssid = temp->sa_data;
1122
1123 if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) {
1124 if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
1125 ret = -1;
1126 spin_unlock_bh(&queue->lock);
1127 goto exit;
1128 }
1129
1130 break;
1131 }
1132 }
1133 spin_unlock_bh(&queue->lock);
1134
1135 rtw_set_802_11_authentication_mode(padapter, authmode);
1136 /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
1137 if (rtw_set_802_11_bssid(padapter, temp->sa_data) == false) {
1138 ret = -1;
1139 goto exit;
1140 }
1141
1142 exit:
1143
1144 return ret;
1145 }
1146
1147 static int rtw_wx_get_wap(struct net_device *dev,
1148 struct iw_request_info *info,
1149 union iwreq_data *wrqu, char *extra)
1150 {
1151 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1152 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1153 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1154
1155 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1156
1157 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1158
1159 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_wap\n"));
1160
1161 if (((check_fwstate(pmlmepriv, _FW_LINKED)) == true) ||
1162 ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true) ||
1163 ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == true))
1164 memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1165 else
1166 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
1167 return 0;
1168 }
1169
1170 static int rtw_wx_set_mlme(struct net_device *dev,
1171 struct iw_request_info *info,
1172 union iwreq_data *wrqu, char *extra)
1173 {
1174 int ret = 0;
1175 u16 reason;
1176 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1177 struct iw_mlme *mlme = (struct iw_mlme *)extra;
1178
1179 if (mlme == NULL)
1180 return -1;
1181
1182 DBG_88E("%s\n", __func__);
1183
1184 reason = mlme->reason_code;
1185
1186 DBG_88E("%s, cmd =%d, reason =%d\n", __func__, mlme->cmd, reason);
1187
1188 switch (mlme->cmd) {
1189 case IW_MLME_DEAUTH:
1190 if (!rtw_set_802_11_disassociate(padapter))
1191 ret = -1;
1192 break;
1193 case IW_MLME_DISASSOC:
1194 if (!rtw_set_802_11_disassociate(padapter))
1195 ret = -1;
1196 break;
1197 default:
1198 return -EOPNOTSUPP;
1199 }
1200 return ret;
1201 }
1202
1203 static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
1204 union iwreq_data *wrqu, char *extra)
1205 {
1206 u8 _status = false;
1207 int ret = 0;
1208 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1209 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1210 struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
1211 #ifdef CONFIG_88EU_P2P
1212 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
1213 #endif /* CONFIG_88EU_P2P */
1214 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_set_scan\n"));
1215
1216 if (padapter->registrypriv.mp_mode == 1) {
1217 if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
1218 ret = -1;
1219 goto exit;
1220 }
1221 }
1222 if (_FAIL == rtw_pwr_wakeup(padapter)) {
1223 ret = -1;
1224 goto exit;
1225 }
1226
1227 if (padapter->bDriverStopped) {
1228 DBG_88E("bDriverStopped =%d\n", padapter->bDriverStopped);
1229 ret = -1;
1230 goto exit;
1231 }
1232
1233 if (!padapter->bup) {
1234 ret = -1;
1235 goto exit;
1236 }
1237
1238 if (!padapter->hw_init_completed) {
1239 ret = -1;
1240 goto exit;
1241 }
1242
1243 /* When Busy Traffic, driver do not site survey. So driver return success. */
1244 /* wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */
1245 /* modify by thomas 2011-02-22. */
1246 if (pmlmepriv->LinkDetectInfo.bBusyTraffic) {
1247 indicate_wx_scan_complete_event(padapter);
1248 goto exit;
1249 }
1250
1251 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
1252 indicate_wx_scan_complete_event(padapter);
1253 goto exit;
1254 }
1255
1256 /* For the DMP WiFi Display project, the driver won't to scan because */
1257 /* the pmlmepriv->scan_interval is always equal to 3. */
1258 /* So, the wpa_supplicant won't find out the WPS SoftAP. */
1259
1260 #ifdef CONFIG_88EU_P2P
1261 if (pwdinfo->p2p_state != P2P_STATE_NONE) {
1262 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
1263 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
1264 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_FULL);
1265 rtw_free_network_queue(padapter, true);
1266 }
1267 #endif /* CONFIG_88EU_P2P */
1268
1269 memset(ssid, 0, sizeof(struct ndis_802_11_ssid)*RTW_SSID_SCAN_AMOUNT);
1270
1271 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1272 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1273
1274 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1275 int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE);
1276
1277 memcpy(ssid[0].Ssid, req->essid, len);
1278 ssid[0].SsidLength = len;
1279
1280 DBG_88E("IW_SCAN_THIS_ESSID, ssid =%s, len =%d\n", req->essid, req->essid_len);
1281
1282 spin_lock_bh(&pmlmepriv->lock);
1283
1284 _status = rtw_sitesurvey_cmd(padapter, ssid, 1, NULL, 0);
1285
1286 spin_unlock_bh(&pmlmepriv->lock);
1287 } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) {
1288 DBG_88E("rtw_wx_set_scan, req->scan_type == IW_SCAN_TYPE_PASSIVE\n");
1289 }
1290 } else {
1291 if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE &&
1292 !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
1293 int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE;
1294 char *pos = extra+WEXT_CSCAN_HEADER_SIZE;
1295 char section;
1296 char sec_len;
1297 int ssid_index = 0;
1298
1299 while (len >= 1) {
1300 section = *(pos++);
1301 len -= 1;
1302
1303 switch (section) {
1304 case WEXT_CSCAN_SSID_SECTION:
1305 if (len < 1) {
1306 len = 0;
1307 break;
1308 }
1309 sec_len = *(pos++); len -= 1;
1310 if (sec_len > 0 && sec_len <= len) {
1311 ssid[ssid_index].SsidLength = sec_len;
1312 memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength);
1313 ssid_index++;
1314 }
1315 pos += sec_len;
1316 len -= sec_len;
1317 break;
1318 case WEXT_CSCAN_TYPE_SECTION:
1319 case WEXT_CSCAN_CHANNEL_SECTION:
1320 pos += 1;
1321 len -= 1;
1322 break;
1323 case WEXT_CSCAN_PASV_DWELL_SECTION:
1324 case WEXT_CSCAN_HOME_DWELL_SECTION:
1325 case WEXT_CSCAN_ACTV_DWELL_SECTION:
1326 pos += 2;
1327 len -= 2;
1328 break;
1329 default:
1330 len = 0; /* stop parsing */
1331 }
1332 }
1333
1334 /* it has still some scan parameter to parse, we only do this now... */
1335 _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
1336 } else {
1337 _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
1338 }
1339 }
1340
1341 if (!_status)
1342 ret = -1;
1343
1344 exit:
1345
1346 return ret;
1347 }
1348
1349 static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
1350 union iwreq_data *wrqu, char *extra)
1351 {
1352 struct list_head *plist, *phead;
1353 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1354 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1355 struct __queue *queue = &(pmlmepriv->scanned_queue);
1356 struct wlan_network *pnetwork = NULL;
1357 char *ev = extra;
1358 char *stop = ev + wrqu->data.length;
1359 u32 ret = 0;
1360 u32 cnt = 0;
1361 u32 wait_for_surveydone;
1362 int wait_status;
1363 #ifdef CONFIG_88EU_P2P
1364 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1365 #endif /* CONFIG_88EU_P2P */
1366 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan\n"));
1367 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, (" Start of Query SIOCGIWSCAN .\n"));
1368
1369 if (padapter->pwrctrlpriv.brfoffbyhw && padapter->bDriverStopped) {
1370 ret = -EINVAL;
1371 goto exit;
1372 }
1373
1374 #ifdef CONFIG_88EU_P2P
1375 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
1376 /* P2P is enabled */
1377 wait_for_surveydone = 200;
1378 } else {
1379 /* P2P is disabled */
1380 wait_for_surveydone = 100;
1381 }
1382 #else
1383 {
1384 wait_for_surveydone = 100;
1385 }
1386 #endif /* CONFIG_88EU_P2P */
1387
1388 wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING;
1389
1390 while (check_fwstate(pmlmepriv, wait_status)) {
1391 msleep(30);
1392 cnt++;
1393 if (cnt > wait_for_surveydone)
1394 break;
1395 }
1396
1397 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1398
1399 phead = get_list_head(queue);
1400 plist = phead->next;
1401
1402 while (phead != plist) {
1403 if ((stop - ev) < SCAN_ITEM_SIZE) {
1404 ret = -E2BIG;
1405 break;
1406 }
1407
1408 pnetwork = container_of(plist, struct wlan_network, list);
1409
1410 /* report network only if the current channel set contains the channel to which this network belongs */
1411 if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0)
1412 ev = translate_scan(padapter, a, pnetwork, ev, stop);
1413
1414 plist = plist->next;
1415 }
1416
1417 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1418
1419 wrqu->data.length = ev-extra;
1420 wrqu->data.flags = 0;
1421
1422 exit:
1423 return ret;
1424 }
1425
1426 /* set ssid flow */
1427 /* s1. rtw_set_802_11_infrastructure_mode() */
1428 /* s2. set_802_11_authenticaion_mode() */
1429 /* s3. set_802_11_encryption_mode() */
1430 /* s4. rtw_set_802_11_ssid() */
1431 static int rtw_wx_set_essid(struct net_device *dev,
1432 struct iw_request_info *a,
1433 union iwreq_data *wrqu, char *extra)
1434 {
1435 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1436 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1437 struct __queue *queue = &pmlmepriv->scanned_queue;
1438 struct list_head *phead;
1439 struct wlan_network *pnetwork = NULL;
1440 enum ndis_802_11_auth_mode authmode;
1441 struct ndis_802_11_ssid ndis_ssid;
1442 u8 *dst_ssid, *src_ssid;
1443
1444 uint ret = 0, len;
1445
1446
1447 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1448 ("+rtw_wx_set_essid: fw_state = 0x%08x\n", get_fwstate(pmlmepriv)));
1449 if (_FAIL == rtw_pwr_wakeup(padapter)) {
1450 ret = -1;
1451 goto exit;
1452 }
1453
1454 if (!padapter->bup) {
1455 ret = -1;
1456 goto exit;
1457 }
1458
1459 if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
1460 ret = -E2BIG;
1461 goto exit;
1462 }
1463
1464 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1465 ret = -1;
1466 goto exit;
1467 }
1468
1469 authmode = padapter->securitypriv.ndisauthtype;
1470 DBG_88E("=>%s\n", __func__);
1471 if (wrqu->essid.flags && wrqu->essid.length) {
1472 len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
1473
1474 if (wrqu->essid.length != 33)
1475 DBG_88E("ssid =%s, len =%d\n", extra, wrqu->essid.length);
1476
1477 memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1478 ndis_ssid.SsidLength = len;
1479 memcpy(ndis_ssid.Ssid, extra, len);
1480 src_ssid = ndis_ssid.Ssid;
1481
1482 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: ssid =[%s]\n", src_ssid));
1483 spin_lock_bh(&queue->lock);
1484 phead = get_list_head(queue);
1485 pmlmepriv->pscanned = phead->next;
1486
1487 while (phead != pmlmepriv->pscanned) {
1488 pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
1489
1490 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1491
1492 dst_ssid = pnetwork->network.Ssid.Ssid;
1493
1494 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1495 ("rtw_wx_set_essid: dst_ssid =%s\n",
1496 pnetwork->network.Ssid.Ssid));
1497
1498 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength)) &&
1499 (pnetwork->network.Ssid.SsidLength == ndis_ssid.SsidLength)) {
1500 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1501 ("rtw_wx_set_essid: find match, set infra mode\n"));
1502
1503 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
1504 if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
1505 continue;
1506 }
1507
1508 if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
1509 ret = -1;
1510 spin_unlock_bh(&queue->lock);
1511 goto exit;
1512 }
1513
1514 break;
1515 }
1516 }
1517 spin_unlock_bh(&queue->lock);
1518 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1519 ("set ssid: set_802_11_auth. mode =%d\n", authmode));
1520 rtw_set_802_11_authentication_mode(padapter, authmode);
1521 if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == false) {
1522 ret = -1;
1523 goto exit;
1524 }
1525 }
1526
1527 exit:
1528
1529 DBG_88E("<=%s, ret %d\n", __func__, ret);
1530
1531
1532 return ret;
1533 }
1534
1535 static int rtw_wx_get_essid(struct net_device *dev,
1536 struct iw_request_info *a,
1537 union iwreq_data *wrqu, char *extra)
1538 {
1539 u32 len, ret = 0;
1540 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1541 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1542 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
1543
1544 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_essid\n"));
1545
1546
1547 if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
1548 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) {
1549 len = pcur_bss->Ssid.SsidLength;
1550
1551 wrqu->essid.length = len;
1552
1553 memcpy(extra, pcur_bss->Ssid.Ssid, len);
1554
1555 wrqu->essid.flags = 1;
1556 } else {
1557 ret = -1;
1558 goto exit;
1559 }
1560
1561 exit:
1562
1563
1564 return ret;
1565 }
1566
1567 static int rtw_wx_set_rate(struct net_device *dev,
1568 struct iw_request_info *a,
1569 union iwreq_data *wrqu, char *extra)
1570 {
1571 int i, ret = 0;
1572 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1573 u8 datarates[NumRates];
1574 u32 target_rate = wrqu->bitrate.value;
1575 u32 fixed = wrqu->bitrate.fixed;
1576 u32 ratevalue = 0;
1577 u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1578
1579
1580 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_set_rate\n"));
1581 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("target_rate = %d, fixed = %d\n", target_rate, fixed));
1582
1583 if (target_rate == -1) {
1584 ratevalue = 11;
1585 goto set_rate;
1586 }
1587 target_rate = target_rate/100000;
1588
1589 switch (target_rate) {
1590 case 10:
1591 ratevalue = 0;
1592 break;
1593 case 20:
1594 ratevalue = 1;
1595 break;
1596 case 55:
1597 ratevalue = 2;
1598 break;
1599 case 60:
1600 ratevalue = 3;
1601 break;
1602 case 90:
1603 ratevalue = 4;
1604 break;
1605 case 110:
1606 ratevalue = 5;
1607 break;
1608 case 120:
1609 ratevalue = 6;
1610 break;
1611 case 180:
1612 ratevalue = 7;
1613 break;
1614 case 240:
1615 ratevalue = 8;
1616 break;
1617 case 360:
1618 ratevalue = 9;
1619 break;
1620 case 480:
1621 ratevalue = 10;
1622 break;
1623 case 540:
1624 ratevalue = 11;
1625 break;
1626 default:
1627 ratevalue = 11;
1628 break;
1629 }
1630
1631 set_rate:
1632
1633 for (i = 0; i < NumRates; i++) {
1634 if (ratevalue == mpdatarate[i]) {
1635 datarates[i] = mpdatarate[i];
1636 if (fixed == 0)
1637 break;
1638 } else {
1639 datarates[i] = 0xff;
1640 }
1641
1642 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("datarate_inx =%d\n", datarates[i]));
1643 }
1644
1645 if (rtw_setdatarate_cmd(padapter, datarates) != _SUCCESS) {
1646 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("rtw_wx_set_rate Fail!!!\n"));
1647 ret = -1;
1648 }
1649
1650
1651 return ret;
1652 }
1653
1654 static int rtw_wx_get_rate(struct net_device *dev,
1655 struct iw_request_info *info,
1656 union iwreq_data *wrqu, char *extra)
1657 {
1658 u16 max_rate = 0;
1659
1660 max_rate = rtw_get_cur_max_rate((struct adapter *)rtw_netdev_priv(dev));
1661
1662 if (max_rate == 0)
1663 return -EPERM;
1664
1665 wrqu->bitrate.fixed = 0; /* no auto select */
1666 wrqu->bitrate.value = max_rate * 100000;
1667
1668 return 0;
1669 }
1670
1671 static int rtw_wx_set_rts(struct net_device *dev,
1672 struct iw_request_info *info,
1673 union iwreq_data *wrqu, char *extra)
1674 {
1675 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1676
1677
1678 if (wrqu->rts.disabled) {
1679 padapter->registrypriv.rts_thresh = 2347;
1680 } else {
1681 if (wrqu->rts.value < 0 ||
1682 wrqu->rts.value > 2347)
1683 return -EINVAL;
1684
1685 padapter->registrypriv.rts_thresh = wrqu->rts.value;
1686 }
1687
1688 DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
1689
1690
1691 return 0;
1692 }
1693
1694 static int rtw_wx_get_rts(struct net_device *dev,
1695 struct iw_request_info *info,
1696 union iwreq_data *wrqu, char *extra)
1697 {
1698 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1699
1700
1701 DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
1702
1703 wrqu->rts.value = padapter->registrypriv.rts_thresh;
1704 wrqu->rts.fixed = 0; /* no auto select */
1705 /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
1706
1707
1708 return 0;
1709 }
1710
1711 static int rtw_wx_set_frag(struct net_device *dev,
1712 struct iw_request_info *info,
1713 union iwreq_data *wrqu, char *extra)
1714 {
1715 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1716
1717
1718 if (wrqu->frag.disabled) {
1719 padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1720 } else {
1721 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1722 wrqu->frag.value > MAX_FRAG_THRESHOLD)
1723 return -EINVAL;
1724
1725 padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1726 }
1727
1728 DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
1729
1730
1731 return 0;
1732 }
1733
1734 static int rtw_wx_get_frag(struct net_device *dev,
1735 struct iw_request_info *info,
1736 union iwreq_data *wrqu, char *extra)
1737 {
1738 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1739
1740
1741 DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
1742
1743 wrqu->frag.value = padapter->xmitpriv.frag_len;
1744 wrqu->frag.fixed = 0; /* no auto select */
1745
1746
1747 return 0;
1748 }
1749
1750 static int rtw_wx_get_retry(struct net_device *dev,
1751 struct iw_request_info *info,
1752 union iwreq_data *wrqu, char *extra)
1753 {
1754 wrqu->retry.value = 7;
1755 wrqu->retry.fixed = 0; /* no auto select */
1756 wrqu->retry.disabled = 1;
1757
1758 return 0;
1759 }
1760
1761 static int rtw_wx_set_enc(struct net_device *dev,
1762 struct iw_request_info *info,
1763 union iwreq_data *wrqu, char *keybuf)
1764 {
1765 u32 key, ret = 0;
1766 u32 keyindex_provided;
1767 struct ndis_802_11_wep wep;
1768 enum ndis_802_11_auth_mode authmode;
1769
1770 struct iw_point *erq = &(wrqu->encoding);
1771 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1772 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
1773 DBG_88E("+rtw_wx_set_enc, flags = 0x%x\n", erq->flags);
1774
1775 memset(&wep, 0, sizeof(struct ndis_802_11_wep));
1776
1777 key = erq->flags & IW_ENCODE_INDEX;
1778
1779
1780 if (erq->flags & IW_ENCODE_DISABLED) {
1781 DBG_88E("EncryptionDisabled\n");
1782 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1783 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1784 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1785 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1786 authmode = Ndis802_11AuthModeOpen;
1787 padapter->securitypriv.ndisauthtype = authmode;
1788
1789 goto exit;
1790 }
1791
1792 if (key) {
1793 if (key > WEP_KEYS)
1794 return -EINVAL;
1795 key--;
1796 keyindex_provided = 1;
1797 } else {
1798 keyindex_provided = 0;
1799 key = padapter->securitypriv.dot11PrivacyKeyIndex;
1800 DBG_88E("rtw_wx_set_enc, key =%d\n", key);
1801 }
1802
1803 /* set authentication mode */
1804 if (erq->flags & IW_ENCODE_OPEN) {
1805 DBG_88E("rtw_wx_set_enc():IW_ENCODE_OPEN\n");
1806 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1807 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1808 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1809 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1810 authmode = Ndis802_11AuthModeOpen;
1811 padapter->securitypriv.ndisauthtype = authmode;
1812 } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1813 DBG_88E("rtw_wx_set_enc():IW_ENCODE_RESTRICTED\n");
1814 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1815 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1816 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1817 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
1818 authmode = Ndis802_11AuthModeShared;
1819 padapter->securitypriv.ndisauthtype = authmode;
1820 } else {
1821 DBG_88E("rtw_wx_set_enc():erq->flags = 0x%x\n", erq->flags);
1822
1823 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1824 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1825 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1826 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1827 authmode = Ndis802_11AuthModeOpen;
1828 padapter->securitypriv.ndisauthtype = authmode;
1829 }
1830
1831 wep.KeyIndex = key;
1832 if (erq->length > 0) {
1833 wep.KeyLength = erq->length <= 5 ? 5 : 13;
1834
1835 wep.Length = wep.KeyLength + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
1836 } else {
1837 wep.KeyLength = 0;
1838
1839 if (keyindex_provided == 1) {
1840 /* set key_id only, no given KeyMaterial(erq->length == 0). */
1841 padapter->securitypriv.dot11PrivacyKeyIndex = key;
1842
1843 DBG_88E("(keyindex_provided == 1), keyid =%d, key_len =%d\n", key, padapter->securitypriv.dot11DefKeylen[key]);
1844
1845 switch (padapter->securitypriv.dot11DefKeylen[key]) {
1846 case 5:
1847 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1848 break;
1849 case 13:
1850 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
1851 break;
1852 default:
1853 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1854 break;
1855 }
1856
1857 goto exit;
1858 }
1859 }
1860
1861 wep.KeyIndex |= 0x80000000;
1862
1863 memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
1864
1865 if (rtw_set_802_11_add_wep(padapter, &wep) == false) {
1866 if (rf_on == pwrpriv->rf_pwrstate)
1867 ret = -EOPNOTSUPP;
1868 goto exit;
1869 }
1870
1871 exit:
1872
1873
1874 return ret;
1875 }
1876
1877 static int rtw_wx_get_enc(struct net_device *dev,
1878 struct iw_request_info *info,
1879 union iwreq_data *wrqu, char *keybuf)
1880 {
1881 uint key, ret = 0;
1882 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1883 struct iw_point *erq = &(wrqu->encoding);
1884 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1885
1886
1887 if (check_fwstate(pmlmepriv, _FW_LINKED) != true) {
1888 if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
1889 erq->length = 0;
1890 erq->flags |= IW_ENCODE_DISABLED;
1891 return 0;
1892 }
1893 }
1894
1895 key = erq->flags & IW_ENCODE_INDEX;
1896
1897 if (key) {
1898 if (key > WEP_KEYS)
1899 return -EINVAL;
1900 key--;
1901 } else {
1902 key = padapter->securitypriv.dot11PrivacyKeyIndex;
1903 }
1904
1905 erq->flags = key + 1;
1906
1907 switch (padapter->securitypriv.ndisencryptstatus) {
1908 case Ndis802_11EncryptionNotSupported:
1909 case Ndis802_11EncryptionDisabled:
1910 erq->length = 0;
1911 erq->flags |= IW_ENCODE_DISABLED;
1912 break;
1913 case Ndis802_11Encryption1Enabled:
1914 erq->length = padapter->securitypriv.dot11DefKeylen[key];
1915 if (erq->length) {
1916 memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
1917
1918 erq->flags |= IW_ENCODE_ENABLED;
1919
1920 if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
1921 erq->flags |= IW_ENCODE_OPEN;
1922 else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
1923 erq->flags |= IW_ENCODE_RESTRICTED;
1924 } else {
1925 erq->length = 0;
1926 erq->flags |= IW_ENCODE_DISABLED;
1927 }
1928 break;
1929 case Ndis802_11Encryption2Enabled:
1930 case Ndis802_11Encryption3Enabled:
1931 erq->length = 16;
1932 erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
1933 break;
1934 default:
1935 erq->length = 0;
1936 erq->flags |= IW_ENCODE_DISABLED;
1937 break;
1938 }
1939
1940 return ret;
1941 }
1942
1943 static int rtw_wx_get_power(struct net_device *dev,
1944 struct iw_request_info *info,
1945 union iwreq_data *wrqu, char *extra)
1946 {
1947 wrqu->power.value = 0;
1948 wrqu->power.fixed = 0; /* no auto select */
1949 wrqu->power.disabled = 1;
1950
1951 return 0;
1952 }
1953
1954 static int rtw_wx_set_gen_ie(struct net_device *dev,
1955 struct iw_request_info *info,
1956 union iwreq_data *wrqu, char *extra)
1957 {
1958 int ret;
1959 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1960
1961 ret = rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
1962 return ret;
1963 }
1964
1965 static int rtw_wx_set_auth(struct net_device *dev,
1966 struct iw_request_info *info,
1967 union iwreq_data *wrqu, char *extra)
1968 {
1969 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1970 struct iw_param *param = (struct iw_param *)&(wrqu->param);
1971 int ret = 0;
1972
1973 switch (param->flags & IW_AUTH_INDEX) {
1974 case IW_AUTH_WPA_VERSION:
1975 break;
1976 case IW_AUTH_CIPHER_PAIRWISE:
1977
1978 break;
1979 case IW_AUTH_CIPHER_GROUP:
1980
1981 break;
1982 case IW_AUTH_KEY_MGMT:
1983 /*
1984 * ??? does not use these parameters
1985 */
1986 break;
1987 case IW_AUTH_TKIP_COUNTERMEASURES:
1988 if (param->value) {
1989 /* wpa_supplicant is enabling the tkip countermeasure. */
1990 padapter->securitypriv.btkip_countermeasure = true;
1991 } else {
1992 /* wpa_supplicant is disabling the tkip countermeasure. */
1993 padapter->securitypriv.btkip_countermeasure = false;
1994 }
1995 break;
1996 case IW_AUTH_DROP_UNENCRYPTED:
1997 /* HACK:
1998 *
1999 * wpa_supplicant calls set_wpa_enabled when the driver
2000 * is loaded and unloaded, regardless of if WPA is being
2001 * used. No other calls are made which can be used to
2002 * determine if encryption will be used or not prior to
2003 * association being expected. If encryption is not being
2004 * used, drop_unencrypted is set to false, else true -- we
2005 * can use this to determine if the CAP_PRIVACY_ON bit should
2006 * be set.
2007 */
2008
2009 if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled)
2010 break;/* it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled, */
2011 /* then it needn't reset it; */
2012
2013 if (param->value) {
2014 padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
2015 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
2016 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
2017 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
2018 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
2019 }
2020
2021 break;
2022 case IW_AUTH_80211_AUTH_ALG:
2023 /*
2024 * It's the starting point of a link layer connection using wpa_supplicant
2025 */
2026 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
2027 LeaveAllPowerSaveMode(padapter);
2028 rtw_disassoc_cmd(padapter, 500, false);
2029 DBG_88E("%s...call rtw_indicate_disconnect\n ", __func__);
2030 rtw_indicate_disconnect(padapter);
2031 rtw_free_assoc_resources(padapter, 1);
2032 }
2033 ret = wpa_set_auth_algs(dev, (u32)param->value);
2034 break;
2035 case IW_AUTH_WPA_ENABLED:
2036 break;
2037 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2038 break;
2039 case IW_AUTH_PRIVACY_INVOKED:
2040 break;
2041 default:
2042 return -EOPNOTSUPP;
2043 }
2044
2045 return ret;
2046 }
2047
2048 static int rtw_wx_set_enc_ext(struct net_device *dev,
2049 struct iw_request_info *info,
2050 union iwreq_data *wrqu, char *extra)
2051 {
2052 char *alg_name;
2053 u32 param_len;
2054 struct ieee_param *param = NULL;
2055 struct iw_point *pencoding = &wrqu->encoding;
2056 struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
2057 int ret = 0;
2058
2059 param_len = sizeof(struct ieee_param) + pext->key_len;
2060 param = (struct ieee_param *)rtw_malloc(param_len);
2061 if (param == NULL)
2062 return -1;
2063
2064 memset(param, 0, param_len);
2065
2066 param->cmd = IEEE_CMD_SET_ENCRYPTION;
2067 memset(param->sta_addr, 0xff, ETH_ALEN);
2068
2069 switch (pext->alg) {
2070 case IW_ENCODE_ALG_NONE:
2071 /* todo: remove key */
2072 /* remove = 1; */
2073 alg_name = "none";
2074 break;
2075 case IW_ENCODE_ALG_WEP:
2076 alg_name = "WEP";
2077 break;
2078 case IW_ENCODE_ALG_TKIP:
2079 alg_name = "TKIP";
2080 break;
2081 case IW_ENCODE_ALG_CCMP:
2082 alg_name = "CCMP";
2083 break;
2084 default:
2085 ret = -1;
2086 goto exit;
2087 }
2088
2089 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
2090
2091 if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
2092 param->u.crypt.set_tx = 1;
2093
2094 /* cliW: WEP does not have group key
2095 * just not checking GROUP key setting
2096 */
2097 if ((pext->alg != IW_ENCODE_ALG_WEP) &&
2098 (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY))
2099 param->u.crypt.set_tx = 0;
2100
2101 param->u.crypt.idx = (pencoding->flags&0x00FF) - 1;
2102
2103 if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
2104 memcpy(param->u.crypt.seq, pext->rx_seq, 8);
2105
2106 if (pext->key_len) {
2107 param->u.crypt.key_len = pext->key_len;
2108 memcpy(param->u.crypt.key, pext + 1, pext->key_len);
2109 }
2110
2111 ret = wpa_set_encryption(dev, param, param_len);
2112
2113 exit:
2114 kfree(param);
2115 return ret;
2116 }
2117
2118 static int rtw_wx_get_nick(struct net_device *dev,
2119 struct iw_request_info *info,
2120 union iwreq_data *wrqu, char *extra)
2121 {
2122 if (extra) {
2123 wrqu->data.length = 14;
2124 wrqu->data.flags = 1;
2125 memcpy(extra, "<WIFI@REALTEK>", 14);
2126 }
2127
2128 /* dump debug info here */
2129 return 0;
2130 }
2131
2132 static int rtw_wx_read32(struct net_device *dev,
2133 struct iw_request_info *info,
2134 union iwreq_data *wrqu, char *extra)
2135 {
2136 struct adapter *padapter;
2137 struct iw_point *p;
2138 u16 len;
2139 u32 addr;
2140 u32 data32;
2141 u32 bytes;
2142 u8 *ptmp;
2143 int rv;
2144 int ret = 0;
2145
2146 padapter = (struct adapter *)rtw_netdev_priv(dev);
2147 p = &wrqu->data;
2148 len = p->length;
2149 ptmp = (u8 *)rtw_malloc(len);
2150 if (NULL == ptmp)
2151 return -ENOMEM;
2152
2153 if (copy_from_user(ptmp, p->pointer, len)) {
2154 ret = -EFAULT;
2155 goto exit;
2156 }
2157
2158 bytes = 0;
2159 addr = 0;
2160 rv = sscanf(ptmp, "%d,%x", &bytes, &addr);
2161 if (rv != 2) {
2162 ret = -EINVAL;
2163 goto exit;
2164 }
2165
2166 switch (bytes) {
2167 case 1:
2168 data32 = usb_read8(padapter, addr);
2169 sprintf(extra, "0x%02X", data32);
2170 break;
2171 case 2:
2172 data32 = usb_read16(padapter, addr);
2173 sprintf(extra, "0x%04X", data32);
2174 break;
2175 case 4:
2176 data32 = usb_read32(padapter, addr);
2177 sprintf(extra, "0x%08X", data32);
2178 break;
2179 default:
2180 DBG_88E(KERN_INFO "%s: usage> read [bytes],[address(hex)]\n", __func__);
2181 ret = -EINVAL;
2182 goto exit;
2183 }
2184 DBG_88E(KERN_INFO "%s: addr = 0x%08X data =%s\n", __func__, addr, extra);
2185
2186 exit:
2187 kfree(ptmp);
2188 return ret;
2189 }
2190
2191 static int rtw_wx_write32(struct net_device *dev,
2192 struct iw_request_info *info,
2193 union iwreq_data *wrqu, char *extra)
2194 {
2195 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2196 int rv;
2197
2198 u32 addr;
2199 u32 data32;
2200 u32 bytes;
2201
2202 bytes = 0;
2203 addr = 0;
2204 data32 = 0;
2205 rv = sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32);
2206 if (rv != 3)
2207 return -EINVAL;
2208
2209 switch (bytes) {
2210 case 1:
2211 usb_write8(padapter, addr, (u8)data32);
2212 DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%02X\n", __func__, addr, (u8)data32);
2213 break;
2214 case 2:
2215 usb_write16(padapter, addr, (u16)data32);
2216 DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%04X\n", __func__, addr, (u16)data32);
2217 break;
2218 case 4:
2219 usb_write32(padapter, addr, data32);
2220 DBG_88E(KERN_INFO "%s: addr = 0x%08X data = 0x%08X\n", __func__, addr, data32);
2221 break;
2222 default:
2223 DBG_88E(KERN_INFO "%s: usage> write [bytes],[address(hex)],[data(hex)]\n", __func__);
2224 return -EINVAL;
2225 }
2226
2227 return 0;
2228 }
2229
2230 static int rtw_wx_read_rf(struct net_device *dev,
2231 struct iw_request_info *info,
2232 union iwreq_data *wrqu, char *extra)
2233 {
2234 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2235 u32 path, addr, data32;
2236
2237 path = *(u32 *)extra;
2238 addr = *((u32 *)extra + 1);
2239 data32 = rtw_hal_read_rfreg(padapter, path, addr, 0xFFFFF);
2240 /*
2241 * IMPORTANT!!
2242 * Only when wireless private ioctl is at odd order,
2243 * "extra" would be copied to user space.
2244 */
2245 sprintf(extra, "0x%05x", data32);
2246
2247 return 0;
2248 }
2249
2250 static int rtw_wx_write_rf(struct net_device *dev,
2251 struct iw_request_info *info,
2252 union iwreq_data *wrqu, char *extra)
2253 {
2254 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2255 u32 path, addr, data32;
2256
2257 path = *(u32 *)extra;
2258 addr = *((u32 *)extra + 1);
2259 data32 = *((u32 *)extra + 2);
2260 rtw_hal_write_rfreg(padapter, path, addr, 0xFFFFF, data32);
2261
2262 return 0;
2263 }
2264
2265 static int rtw_wx_priv_null(struct net_device *dev, struct iw_request_info *a,
2266 union iwreq_data *wrqu, char *b)
2267 {
2268 return -1;
2269 }
2270
2271 static int dummy(struct net_device *dev, struct iw_request_info *a,
2272 union iwreq_data *wrqu, char *b)
2273 {
2274 return -1;
2275 }
2276
2277 static int rtw_wx_set_channel_plan(struct net_device *dev,
2278 struct iw_request_info *info,
2279 union iwreq_data *wrqu, char *extra)
2280 {
2281 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2282 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2283 u8 channel_plan_req = (u8) (*((int *)wrqu));
2284
2285 if (_SUCCESS == rtw_set_chplan_cmd(padapter, channel_plan_req, 1))
2286 DBG_88E("%s set channel_plan = 0x%02X\n", __func__, pmlmepriv->ChannelPlan);
2287 else
2288 return -EPERM;
2289
2290 return 0;
2291 }
2292
2293 static int rtw_wx_set_mtk_wps_probe_ie(struct net_device *dev,
2294 struct iw_request_info *a,
2295 union iwreq_data *wrqu, char *b)
2296 {
2297 return 0;
2298 }
2299
2300 static int rtw_wx_get_sensitivity(struct net_device *dev,
2301 struct iw_request_info *info,
2302 union iwreq_data *wrqu, char *buf)
2303 {
2304 return 0;
2305 }
2306
2307 static int rtw_wx_set_mtk_wps_ie(struct net_device *dev,
2308 struct iw_request_info *info,
2309 union iwreq_data *wrqu, char *extra)
2310 {
2311 return 0;
2312 }
2313
2314 /*
2315 * For all data larger than 16 octets, we need to use a
2316 * pointer to memory allocated in user space.
2317 */
2318 static int rtw_drvext_hdl(struct net_device *dev, struct iw_request_info *info,
2319 union iwreq_data *wrqu, char *extra)
2320 {
2321 return 0;
2322 }
2323
2324 static void rtw_dbg_mode_hdl(struct adapter *padapter, u32 id, u8 *pdata, u32 len)
2325 {
2326 struct mp_rw_reg *RegRWStruct;
2327 struct rf_reg_param *prfreg;
2328 u8 path;
2329 u8 offset;
2330 u32 value;
2331
2332 DBG_88E("%s\n", __func__);
2333
2334 switch (id) {
2335 case GEN_MP_IOCTL_SUBCODE(MP_START):
2336 DBG_88E("871x_driver is only for normal mode, can't enter mp mode\n");
2337 break;
2338 case GEN_MP_IOCTL_SUBCODE(READ_REG):
2339 RegRWStruct = (struct mp_rw_reg *)pdata;
2340 switch (RegRWStruct->width) {
2341 case 1:
2342 RegRWStruct->value = usb_read8(padapter, RegRWStruct->offset);
2343 break;
2344 case 2:
2345 RegRWStruct->value = usb_read16(padapter, RegRWStruct->offset);
2346 break;
2347 case 4:
2348 RegRWStruct->value = usb_read32(padapter, RegRWStruct->offset);
2349 break;
2350 default:
2351 break;
2352 }
2353
2354 break;
2355 case GEN_MP_IOCTL_SUBCODE(WRITE_REG):
2356 RegRWStruct = (struct mp_rw_reg *)pdata;
2357 switch (RegRWStruct->width) {
2358 case 1:
2359 usb_write8(padapter, RegRWStruct->offset, (u8)RegRWStruct->value);
2360 break;
2361 case 2:
2362 usb_write16(padapter, RegRWStruct->offset, (u16)RegRWStruct->value);
2363 break;
2364 case 4:
2365 usb_write32(padapter, RegRWStruct->offset, (u32)RegRWStruct->value);
2366 break;
2367 default:
2368 break;
2369 }
2370
2371 break;
2372 case GEN_MP_IOCTL_SUBCODE(READ_RF_REG):
2373
2374 prfreg = (struct rf_reg_param *)pdata;
2375
2376 path = (u8)prfreg->path;
2377 offset = (u8)prfreg->offset;
2378
2379 value = rtw_hal_read_rfreg(padapter, path, offset, 0xffffffff);
2380
2381 prfreg->value = value;
2382
2383 break;
2384 case GEN_MP_IOCTL_SUBCODE(WRITE_RF_REG):
2385
2386 prfreg = (struct rf_reg_param *)pdata;
2387
2388 path = (u8)prfreg->path;
2389 offset = (u8)prfreg->offset;
2390 value = prfreg->value;
2391
2392 rtw_hal_write_rfreg(padapter, path, offset, 0xffffffff, value);
2393
2394 break;
2395 case GEN_MP_IOCTL_SUBCODE(TRIGGER_GPIO):
2396 DBG_88E("==> trigger gpio 0\n");
2397 rtw_hal_set_hwreg(padapter, HW_VAR_TRIGGER_GPIO_0, NULL);
2398 break;
2399 case GEN_MP_IOCTL_SUBCODE(GET_WIFI_STATUS):
2400 *pdata = rtw_hal_sreset_get_wifi_status(padapter);
2401 break;
2402 default:
2403 break;
2404 }
2405 }
2406
2407 static int rtw_mp_ioctl_hdl(struct net_device *dev, struct iw_request_info *info,
2408 union iwreq_data *wrqu, char *extra)
2409 {
2410 int ret = 0;
2411 u32 BytesRead, BytesWritten, BytesNeeded;
2412 struct oid_par_priv oid_par;
2413 struct mp_ioctl_handler *phandler;
2414 struct mp_ioctl_param *poidparam;
2415 uint status = 0;
2416 u16 len;
2417 u8 *pparmbuf = NULL, bset;
2418 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2419 struct iw_point *p = &wrqu->data;
2420
2421 if ((!p->length) || (!p->pointer)) {
2422 ret = -EINVAL;
2423 goto _rtw_mp_ioctl_hdl_exit;
2424 }
2425 pparmbuf = NULL;
2426 bset = (u8)(p->flags & 0xFFFF);
2427 len = p->length;
2428 pparmbuf = (u8 *)rtw_malloc(len);
2429 if (pparmbuf == NULL) {
2430 ret = -ENOMEM;
2431 goto _rtw_mp_ioctl_hdl_exit;
2432 }
2433
2434 if (copy_from_user(pparmbuf, p->pointer, len)) {
2435 ret = -EFAULT;
2436 goto _rtw_mp_ioctl_hdl_exit;
2437 }
2438
2439 poidparam = (struct mp_ioctl_param *)pparmbuf;
2440 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
2441 ("rtw_mp_ioctl_hdl: subcode [%d], len[%d], buffer_len[%d]\r\n",
2442 poidparam->subcode, poidparam->len, len));
2443
2444 if (poidparam->subcode >= ARRAY_SIZE(mp_ioctl_hdl)) {
2445 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("no matching drvext subcodes\r\n"));
2446 ret = -EINVAL;
2447 goto _rtw_mp_ioctl_hdl_exit;
2448 }
2449
2450 if (padapter->registrypriv.mp_mode == 1) {
2451 phandler = mp_ioctl_hdl + poidparam->subcode;
2452
2453 if ((phandler->paramsize != 0) && (poidparam->len < phandler->paramsize)) {
2454 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
2455 ("no matching drvext param size %d vs %d\r\n",
2456 poidparam->len, phandler->paramsize));
2457 ret = -EINVAL;
2458 goto _rtw_mp_ioctl_hdl_exit;
2459 }
2460
2461 if (phandler->handler) {
2462 oid_par.adapter_context = padapter;
2463 oid_par.oid = phandler->oid;
2464 oid_par.information_buf = poidparam->data;
2465 oid_par.information_buf_len = poidparam->len;
2466 oid_par.dbg = 0;
2467
2468 BytesWritten = 0;
2469 BytesNeeded = 0;
2470
2471 if (bset) {
2472 oid_par.bytes_rw = &BytesRead;
2473 oid_par.bytes_needed = &BytesNeeded;
2474 oid_par.type_of_oid = SET_OID;
2475 } else {
2476 oid_par.bytes_rw = &BytesWritten;
2477 oid_par.bytes_needed = &BytesNeeded;
2478 oid_par.type_of_oid = QUERY_OID;
2479 }
2480
2481 status = phandler->handler(&oid_par);
2482 } else {
2483 DBG_88E("rtw_mp_ioctl_hdl(): err!, subcode =%d, oid =%d, handler =%p\n",
2484 poidparam->subcode, phandler->oid, phandler->handler);
2485 ret = -EFAULT;
2486 goto _rtw_mp_ioctl_hdl_exit;
2487 }
2488 } else {
2489 rtw_dbg_mode_hdl(padapter, poidparam->subcode, poidparam->data, poidparam->len);
2490 }
2491
2492 if (bset == 0x00) {/* query info */
2493 if (copy_to_user(p->pointer, pparmbuf, len))
2494 ret = -EFAULT;
2495 }
2496
2497 if (status) {
2498 ret = -EFAULT;
2499 goto _rtw_mp_ioctl_hdl_exit;
2500 }
2501
2502 _rtw_mp_ioctl_hdl_exit:
2503
2504 kfree(pparmbuf);
2505 return ret;
2506 }
2507
2508 static int rtw_get_ap_info(struct net_device *dev,
2509 struct iw_request_info *info,
2510 union iwreq_data *wrqu, char *extra)
2511 {
2512 int ret = 0;
2513 u32 cnt = 0, wpa_ielen;
2514 struct list_head *plist, *phead;
2515 unsigned char *pbuf;
2516 u8 bssid[ETH_ALEN];
2517 char data[32];
2518 struct wlan_network *pnetwork = NULL;
2519 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2520 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2521 struct __queue *queue = &(pmlmepriv->scanned_queue);
2522 struct iw_point *pdata = &wrqu->data;
2523
2524 DBG_88E("+rtw_get_aplist_info\n");
2525
2526 if ((padapter->bDriverStopped) || (pdata == NULL)) {
2527 ret = -EINVAL;
2528 goto exit;
2529 }
2530
2531 while ((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)))) {
2532 msleep(30);
2533 cnt++;
2534 if (cnt > 100)
2535 break;
2536 }
2537 pdata->flags = 0;
2538 if (pdata->length >= 32) {
2539 if (copy_from_user(data, pdata->pointer, 32)) {
2540 ret = -EINVAL;
2541 goto exit;
2542 }
2543 } else {
2544 ret = -EINVAL;
2545 goto exit;
2546 }
2547
2548 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
2549
2550 phead = get_list_head(queue);
2551 plist = phead->next;
2552
2553 while (phead != plist) {
2554 pnetwork = container_of(plist, struct wlan_network, list);
2555
2556 if (hwaddr_aton_i(data, bssid)) {
2557 DBG_88E("Invalid BSSID '%s'.\n", (u8 *)data);
2558 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
2559 return -EINVAL;
2560 }
2561
2562 if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
2563 /* BSSID match, then check if supporting wpa/wpa2 */
2564 DBG_88E("BSSID:%pM\n", (bssid));
2565
2566 pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
2567 if (pbuf && (wpa_ielen > 0)) {
2568 pdata->flags = 1;
2569 break;
2570 }
2571
2572 pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
2573 if (pbuf && (wpa_ielen > 0)) {
2574 pdata->flags = 2;
2575 break;
2576 }
2577 }
2578
2579 plist = plist->next;
2580 }
2581
2582 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
2583
2584 if (pdata->length >= 34) {
2585 if (copy_to_user(pdata->pointer+32, (u8 *)&pdata->flags, 1)) {
2586 ret = -EINVAL;
2587 goto exit;
2588 }
2589 }
2590
2591 exit:
2592
2593 return ret;
2594 }
2595
2596 static int rtw_set_pid(struct net_device *dev,
2597 struct iw_request_info *info,
2598 union iwreq_data *wrqu, char *extra)
2599 {
2600 int ret = 0;
2601 struct adapter *padapter = rtw_netdev_priv(dev);
2602 int *pdata = (int *)wrqu;
2603 int selector;
2604
2605 if ((padapter->bDriverStopped) || (pdata == NULL)) {
2606 ret = -EINVAL;
2607 goto exit;
2608 }
2609
2610 selector = *pdata;
2611 if (selector < 3 && selector >= 0) {
2612 padapter->pid[selector] = *(pdata+1);
2613 ui_pid[selector] = *(pdata+1);
2614 DBG_88E("%s set pid[%d] =%d\n", __func__, selector, padapter->pid[selector]);
2615 } else {
2616 DBG_88E("%s selector %d error\n", __func__, selector);
2617 }
2618 exit:
2619 return ret;
2620 }
2621
2622 static int rtw_wps_start(struct net_device *dev,
2623 struct iw_request_info *info,
2624 union iwreq_data *wrqu, char *extra)
2625 {
2626 int ret = 0;
2627 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2628 struct iw_point *pdata = &wrqu->data;
2629 u32 u32wps_start = 0;
2630
2631 if ((padapter->bDriverStopped) || (pdata == NULL)) {
2632 ret = -EINVAL;
2633 goto exit;
2634 }
2635
2636 ret = copy_from_user((void *)&u32wps_start, pdata->pointer, 4);
2637 if (ret) {
2638 ret = -EINVAL;
2639 goto exit;
2640 }
2641
2642 if (u32wps_start == 0)
2643 u32wps_start = *extra;
2644
2645 DBG_88E("[%s] wps_start = %d\n", __func__, u32wps_start);
2646
2647 if (u32wps_start == 1) /* WPS Start */
2648 rtw_led_control(padapter, LED_CTL_START_WPS);
2649 else if (u32wps_start == 2) /* WPS Stop because of wps success */
2650 rtw_led_control(padapter, LED_CTL_STOP_WPS);
2651 else if (u32wps_start == 3) /* WPS Stop because of wps fail */
2652 rtw_led_control(padapter, LED_CTL_STOP_WPS_FAIL);
2653
2654 exit:
2655 return ret;
2656 }
2657
2658 #ifdef CONFIG_88EU_P2P
2659 static int rtw_wext_p2p_enable(struct net_device *dev,
2660 struct iw_request_info *info,
2661 union iwreq_data *wrqu, char *extra)
2662 {
2663 int ret = 0;
2664 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2665 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2666 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2667 enum P2P_ROLE init_role = P2P_ROLE_DISABLE;
2668
2669 if (*extra == '0')
2670 init_role = P2P_ROLE_DISABLE;
2671 else if (*extra == '1')
2672 init_role = P2P_ROLE_DEVICE;
2673 else if (*extra == '2')
2674 init_role = P2P_ROLE_CLIENT;
2675 else if (*extra == '3')
2676 init_role = P2P_ROLE_GO;
2677
2678 if (_FAIL == rtw_p2p_enable(padapter, init_role)) {
2679 ret = -EFAULT;
2680 goto exit;
2681 }
2682
2683 /* set channel/bandwidth */
2684 if (init_role != P2P_ROLE_DISABLE) {
2685 u8 channel, ch_offset;
2686 u16 bwmode;
2687
2688 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN)) {
2689 /* Stay at the listen state and wait for discovery. */
2690 channel = pwdinfo->listen_channel;
2691 pwdinfo->operating_channel = pwdinfo->listen_channel;
2692 ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2693 bwmode = HT_CHANNEL_WIDTH_20;
2694 } else {
2695 pwdinfo->operating_channel = pmlmeext->cur_channel;
2696
2697 channel = pwdinfo->operating_channel;
2698 ch_offset = pmlmeext->cur_ch_offset;
2699 bwmode = pmlmeext->cur_bwmode;
2700 }
2701
2702 set_channel_bwmode(padapter, channel, ch_offset, bwmode);
2703 }
2704
2705 exit:
2706 return ret;
2707 }
2708
2709 static int rtw_p2p_set_go_nego_ssid(struct net_device *dev,
2710 struct iw_request_info *info,
2711 union iwreq_data *wrqu, char *extra)
2712 {
2713 int ret = 0;
2714 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2715 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2716
2717 DBG_88E("[%s] ssid = %s, len = %zu\n", __func__, extra, strlen(extra));
2718 memcpy(pwdinfo->nego_ssid, extra, strlen(extra));
2719 pwdinfo->nego_ssidlen = strlen(extra);
2720
2721 return ret;
2722 }
2723
2724 static int rtw_p2p_set_intent(struct net_device *dev,
2725 struct iw_request_info *info,
2726 union iwreq_data *wrqu, char *extra)
2727 {
2728 int ret = 0;
2729 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2730 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2731 u8 intent = pwdinfo->intent;
2732
2733 switch (wrqu->data.length) {
2734 case 1:
2735 intent = extra[0] - '0';
2736 break;
2737 case 2:
2738 intent = str_2char2num(extra[0], extra[1]);
2739 break;
2740 }
2741 if (intent <= 15)
2742 pwdinfo->intent = intent;
2743 else
2744 ret = -1;
2745 DBG_88E("[%s] intent = %d\n", __func__, intent);
2746 return ret;
2747 }
2748
2749 static int rtw_p2p_set_listen_ch(struct net_device *dev,
2750 struct iw_request_info *info,
2751 union iwreq_data *wrqu, char *extra)
2752 {
2753 int ret = 0;
2754 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2755 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2756 u8 listen_ch = pwdinfo->listen_channel; /* Listen channel number */
2757
2758 switch (wrqu->data.length) {
2759 case 1:
2760 listen_ch = extra[0] - '0';
2761 break;
2762 case 2:
2763 listen_ch = str_2char2num(extra[0], extra[1]);
2764 break;
2765 }
2766
2767 if ((listen_ch == 1) || (listen_ch == 6) || (listen_ch == 11)) {
2768 pwdinfo->listen_channel = listen_ch;
2769 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
2770 } else {
2771 ret = -1;
2772 }
2773
2774 DBG_88E("[%s] listen_ch = %d\n", __func__, pwdinfo->listen_channel);
2775
2776 return ret;
2777 }
2778
2779 static int rtw_p2p_set_op_ch(struct net_device *dev,
2780 struct iw_request_info *info,
2781 union iwreq_data *wrqu, char *extra)
2782 {
2783 /* Commented by Albert 20110524 */
2784 /* This function is used to set the operating channel if the driver will become the group owner */
2785
2786 int ret = 0;
2787 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2788 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2789 u8 op_ch = pwdinfo->operating_channel; /* Operating channel number */
2790
2791 switch (wrqu->data.length) {
2792 case 1:
2793 op_ch = extra[0] - '0';
2794 break;
2795 case 2:
2796 op_ch = str_2char2num(extra[0], extra[1]);
2797 break;
2798 }
2799
2800 if (op_ch > 0)
2801 pwdinfo->operating_channel = op_ch;
2802 else
2803 ret = -1;
2804
2805 DBG_88E("[%s] op_ch = %d\n", __func__, pwdinfo->operating_channel);
2806
2807 return ret;
2808 }
2809
2810 static int rtw_p2p_profilefound(struct net_device *dev,
2811 struct iw_request_info *info,
2812 union iwreq_data *wrqu, char *extra)
2813 {
2814 int ret = 0;
2815 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2816 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2817
2818 /* Comment by Albert 2010/10/13 */
2819 /* Input data format: */
2820 /* Ex: 0 */
2821 /* Ex: 1XX:XX:XX:XX:XX:XXYYSSID */
2822 /* 0 => Reflush the profile record list. */
2823 /* 1 => Add the profile list */
2824 /* XX:XX:XX:XX:XX:XX => peer's MAC Address (ex: 00:E0:4C:00:00:01) */
2825 /* YY => SSID Length */
2826 /* SSID => SSID for persistence group */
2827
2828 DBG_88E("[%s] In value = %s, len = %d\n", __func__, extra, wrqu->data.length - 1);
2829
2830 /* The upper application should pass the SSID to driver by using this rtw_p2p_profilefound function. */
2831 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
2832 if (extra[0] == '0') {
2833 /* Remove all the profile information of wifidirect_info structure. */
2834 memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
2835 pwdinfo->profileindex = 0;
2836 } else {
2837 if (pwdinfo->profileindex >= P2P_MAX_PERSISTENT_GROUP_NUM) {
2838 ret = -1;
2839 } else {
2840 int jj, kk;
2841
2842 /* Add this profile information into pwdinfo->profileinfo */
2843 /* Ex: 1XX:XX:XX:XX:XX:XXYYSSID */
2844 for (jj = 0, kk = 1; jj < ETH_ALEN; jj++, kk += 3)
2845 pwdinfo->profileinfo[pwdinfo->profileindex].peermac[jj] = key_2char2num(extra[kk], extra[kk + 1]);
2846
2847 pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen = (extra[18] - '0') * 10 + (extra[19] - '0');
2848 memcpy(pwdinfo->profileinfo[pwdinfo->profileindex].ssid, &extra[20], pwdinfo->profileinfo[pwdinfo->profileindex].ssidlen);
2849 pwdinfo->profileindex++;
2850 }
2851 }
2852 }
2853
2854 return ret;
2855 }
2856
2857 static int rtw_p2p_setDN(struct net_device *dev,
2858 struct iw_request_info *info,
2859 union iwreq_data *wrqu, char *extra)
2860 {
2861 int ret = 0;
2862 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2863 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2864
2865 DBG_88E("[%s] %s %d\n", __func__, extra, wrqu->data.length - 1);
2866 memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
2867 memcpy(pwdinfo->device_name, extra, wrqu->data.length - 1);
2868 pwdinfo->device_name_len = wrqu->data.length - 1;
2869
2870 return ret;
2871 }
2872
2873 static int rtw_p2p_get_status(struct net_device *dev,
2874 struct iw_request_info *info,
2875 union iwreq_data *wrqu, char *extra)
2876 {
2877 int ret = 0;
2878 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2879 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2880
2881 if (padapter->bShowGetP2PState)
2882 DBG_88E("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
2883 pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
2884 pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
2885
2886 /* Commented by Albert 2010/10/12 */
2887 /* Because of the output size limitation, I had removed the "Role" information. */
2888 /* About the "Role" information, we will use the new private IOCTL to get the "Role" information. */
2889 sprintf(extra, "\n\nStatus=%.2d\n", rtw_p2p_state(pwdinfo));
2890 wrqu->data.length = strlen(extra);
2891
2892 return ret;
2893 }
2894
2895 /* Commented by Albert 20110520 */
2896 /* This function will return the config method description */
2897 /* This config method description will show us which config method the remote P2P device is intended to use */
2898 /* by sending the provisioning discovery request frame. */
2899
2900 static int rtw_p2p_get_req_cm(struct net_device *dev,
2901 struct iw_request_info *info,
2902 union iwreq_data *wrqu, char *extra)
2903 {
2904 int ret = 0;
2905 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2906 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2907
2908 sprintf(extra, "\n\nCM=%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
2909 wrqu->data.length = strlen(extra);
2910 return ret;
2911 }
2912
2913 static int rtw_p2p_get_role(struct net_device *dev,
2914 struct iw_request_info *info,
2915 union iwreq_data *wrqu, char *extra)
2916 {
2917 int ret = 0;
2918 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2919 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2920
2921 DBG_88E("[%s] Role = %d, Status = %d, peer addr = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
2922 pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
2923 pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
2924
2925 sprintf(extra, "\n\nRole=%.2d\n", rtw_p2p_role(pwdinfo));
2926 wrqu->data.length = strlen(extra);
2927 return ret;
2928 }
2929
2930 static int rtw_p2p_get_peer_ifaddr(struct net_device *dev,
2931 struct iw_request_info *info,
2932 union iwreq_data *wrqu, char *extra)
2933 {
2934 int ret = 0;
2935 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2936 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2937
2938 DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n", __func__,
2939 rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
2940 pwdinfo->p2p_peer_interface_addr);
2941 sprintf(extra, "\nMAC %pM",
2942 pwdinfo->p2p_peer_interface_addr);
2943 wrqu->data.length = strlen(extra);
2944 return ret;
2945 }
2946
2947 static int rtw_p2p_get_peer_devaddr(struct net_device *dev,
2948 struct iw_request_info *info,
2949 union iwreq_data *wrqu, char *extra)
2950
2951 {
2952 int ret = 0;
2953 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2954 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2955
2956 DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n", __func__,
2957 rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
2958 pwdinfo->rx_prov_disc_info.peerDevAddr);
2959 sprintf(extra, "\n%pM",
2960 pwdinfo->rx_prov_disc_info.peerDevAddr);
2961 wrqu->data.length = strlen(extra);
2962 return ret;
2963 }
2964
2965 static int rtw_p2p_get_peer_devaddr_by_invitation(struct net_device *dev,
2966 struct iw_request_info *info,
2967 union iwreq_data *wrqu, char *extra)
2968
2969 {
2970 int ret = 0;
2971 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2972 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2973
2974 DBG_88E("[%s] Role = %d, Status = %d, peer addr = %pM\n",
2975 __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo),
2976 pwdinfo->p2p_peer_device_addr);
2977 sprintf(extra, "\nMAC %pM",
2978 pwdinfo->p2p_peer_device_addr);
2979 wrqu->data.length = strlen(extra);
2980 return ret;
2981 }
2982
2983 static int rtw_p2p_get_groupid(struct net_device *dev,
2984 struct iw_request_info *info,
2985 union iwreq_data *wrqu, char *extra)
2986
2987 {
2988 int ret = 0;
2989 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2990 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2991
2992 sprintf(extra, "\n%.2X:%.2X:%.2X:%.2X:%.2X:%.2X %s",
2993 pwdinfo->groupid_info.go_device_addr[0], pwdinfo->groupid_info.go_device_addr[1],
2994 pwdinfo->groupid_info.go_device_addr[2], pwdinfo->groupid_info.go_device_addr[3],
2995 pwdinfo->groupid_info.go_device_addr[4], pwdinfo->groupid_info.go_device_addr[5],
2996 pwdinfo->groupid_info.ssid);
2997 wrqu->data.length = strlen(extra);
2998 return ret;
2999 }
3000
3001 static int rtw_p2p_get_op_ch(struct net_device *dev,
3002 struct iw_request_info *info,
3003 union iwreq_data *wrqu, char *extra)
3004
3005 {
3006 int ret = 0;
3007 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3008 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3009
3010 DBG_88E("[%s] Op_ch = %02x\n", __func__, pwdinfo->operating_channel);
3011
3012 sprintf(extra, "\n\nOp_ch=%.2d\n", pwdinfo->operating_channel);
3013 wrqu->data.length = strlen(extra);
3014 return ret;
3015 }
3016
3017 static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
3018 struct iw_request_info *info,
3019 union iwreq_data *wrqu, char *extra)
3020 {
3021 int ret = 0;
3022 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3023 u8 peerMAC[ETH_ALEN] = {0x00};
3024 int jj, kk;
3025 u8 peerMACStr[17] = {0x00};
3026 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3027 struct list_head *plist, *phead;
3028 struct __queue *queue = &(pmlmepriv->scanned_queue);
3029 struct wlan_network *pnetwork = NULL;
3030 u8 blnMatch = 0;
3031 u16 attr_content = 0;
3032 uint attr_contentlen = 0;
3033 /* 6 is the string "wpsCM=", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */
3034 u8 attr_content_str[6 + 17] = {0x00};
3035
3036 /* Commented by Albert 20110727 */
3037 /* The input data is the MAC address which the application wants to know its WPS config method. */
3038 /* After knowing its WPS config method, the application can decide the config method for provisioning discovery. */
3039 /* Format: iwpriv wlanx p2p_get_wpsCM 00:E0:4C:00:00:05 */
3040
3041 DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
3042 if (copy_from_user(peerMACStr, wrqu->data.pointer + 6, 17))
3043 return -EFAULT;
3044
3045 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3046 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
3047
3048 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3049
3050 phead = get_list_head(queue);
3051 plist = phead->next;
3052
3053 while (phead != plist) {
3054 pnetwork = container_of(plist, struct wlan_network, list);
3055 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3056 u8 *wpsie;
3057 uint wpsie_len = 0;
3058 __be16 be_tmp;
3059
3060 /* The mac address is matched. */
3061 wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len);
3062 if (wpsie) {
3063 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *) &be_tmp, &attr_contentlen);
3064 if (attr_contentlen) {
3065 attr_content = be16_to_cpu(be_tmp);
3066 sprintf(attr_content_str, "\n\nM=%.4d", attr_content);
3067 blnMatch = 1;
3068 }
3069 }
3070 break;
3071 }
3072 plist = plist->next;
3073 }
3074
3075 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3076
3077 if (!blnMatch)
3078 sprintf(attr_content_str, "\n\nM=0000");
3079
3080 if (copy_to_user(wrqu->data.pointer, attr_content_str, 6 + 17))
3081 return -EFAULT;
3082 return ret;
3083 }
3084
3085 static int rtw_p2p_get_go_device_address(struct net_device *dev,
3086 struct iw_request_info *info,
3087 union iwreq_data *wrqu, char *extra)
3088 {
3089 int ret = 0;
3090 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3091 u8 peerMAC[ETH_ALEN] = {0x00};
3092 int jj, kk;
3093 u8 peerMACStr[17] = {0x00};
3094 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3095 struct list_head *plist, *phead;
3096 struct __queue *queue = &(pmlmepriv->scanned_queue);
3097 struct wlan_network *pnetwork = NULL;
3098 u8 blnMatch = 0;
3099 u8 *p2pie;
3100 uint p2pielen = 0, attr_contentlen = 0;
3101 u8 attr_content[100] = {0x00};
3102 u8 go_devadd_str[17 + 12] = {};
3103
3104 /* Commented by Albert 20121209 */
3105 /* The input data is the GO's interface address which the application wants to know its device address. */
3106 /* Format: iwpriv wlanx p2p_get2 go_devadd = 00:E0:4C:00:00:05 */
3107
3108 DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
3109 if (copy_from_user(peerMACStr, wrqu->data.pointer + 10, 17))
3110 return -EFAULT;
3111
3112 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3113 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
3114
3115 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3116
3117 phead = get_list_head(queue);
3118 plist = phead->next;
3119
3120 while (phead != plist) {
3121 pnetwork = container_of(plist, struct wlan_network, list);
3122 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3123 /* Commented by Albert 2011/05/18 */
3124 /* Match the device address located in the P2P IE */
3125 /* This is for the case that the P2P device address is not the same as the P2P interface address. */
3126
3127 p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
3128 if (p2pie) {
3129 while (p2pie) {
3130 /* The P2P Device ID attribute is included in the Beacon frame. */
3131 /* The P2P Device Info attribute is included in the probe response frame. */
3132
3133 memset(attr_content, 0x00, 100);
3134 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
3135 /* Handle the P2P Device ID attribute of Beacon first */
3136 blnMatch = 1;
3137 break;
3138 } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
3139 /* Handle the P2P Device Info attribute of probe response */
3140 blnMatch = 1;
3141 break;
3142 }
3143
3144 /* Get the next P2P IE */
3145 p2pie = rtw_get_p2p_ie(p2pie+p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
3146 }
3147 }
3148 }
3149
3150 plist = plist->next;
3151 }
3152
3153 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3154
3155 if (!blnMatch)
3156 snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add=NULL");
3157 else
3158 snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add=%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
3159 attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]);
3160
3161 if (copy_to_user(wrqu->data.pointer, go_devadd_str, sizeof(go_devadd_str)))
3162 return -EFAULT;
3163 return ret;
3164 }
3165
3166 static int rtw_p2p_get_device_type(struct net_device *dev,
3167 struct iw_request_info *info,
3168 union iwreq_data *wrqu, char *extra)
3169 {
3170 int ret = 0;
3171 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3172 u8 peerMAC[ETH_ALEN] = {0x00};
3173 int jj, kk;
3174 u8 peerMACStr[17] = {0x00};
3175 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3176 struct list_head *plist, *phead;
3177 struct __queue *queue = &(pmlmepriv->scanned_queue);
3178 struct wlan_network *pnetwork = NULL;
3179 u8 blnMatch = 0;
3180 u8 dev_type[8] = {0x00};
3181 uint dev_type_len = 0;
3182 u8 dev_type_str[17 + 9] = {0x00}; /* +9 is for the str "dev_type=", we have to clear it at wrqu->data.pointer */
3183
3184 /* Commented by Albert 20121209 */
3185 /* The input data is the MAC address which the application wants to know its device type. */
3186 /* Such user interface could know the device type. */
3187 /* Format: iwpriv wlanx p2p_get2 dev_type = 00:E0:4C:00:00:05 */
3188
3189 DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
3190 if (copy_from_user(peerMACStr, wrqu->data.pointer + 9, 17))
3191 return -EFAULT;
3192
3193 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3194 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
3195
3196 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3197
3198 phead = get_list_head(queue);
3199 plist = phead->next;
3200
3201 while (phead != plist) {
3202 pnetwork = container_of(plist, struct wlan_network, list);
3203 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3204 u8 *wpsie;
3205 uint wpsie_len = 0;
3206
3207 /* The mac address is matched. */
3208
3209 wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12],
3210 pnetwork->network.IELength - 12,
3211 NULL, &wpsie_len);
3212 if (wpsie) {
3213 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_PRIMARY_DEV_TYPE, dev_type, &dev_type_len);
3214 if (dev_type_len) {
3215 u16 type = 0;
3216 __be16 be_tmp;
3217
3218 memcpy(&be_tmp, dev_type, 2);
3219 type = be16_to_cpu(be_tmp);
3220 sprintf(dev_type_str, "\n\nN=%.2d", type);
3221 blnMatch = 1;
3222 }
3223 }
3224 break;
3225 }
3226
3227 plist = plist->next;
3228 }
3229
3230 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3231
3232 if (!blnMatch)
3233 sprintf(dev_type_str, "\n\nN=00");
3234
3235 if (copy_to_user(wrqu->data.pointer, dev_type_str, 9 + 17)) {
3236 return -EFAULT;
3237 }
3238
3239 return ret;
3240 }
3241
3242 static int rtw_p2p_get_device_name(struct net_device *dev,
3243 struct iw_request_info *info,
3244 union iwreq_data *wrqu, char *extra)
3245 {
3246 int ret = 0;
3247 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3248 u8 peerMAC[ETH_ALEN] = {0x00};
3249 int jj, kk;
3250 u8 peerMACStr[17] = {0x00};
3251 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3252 struct list_head *plist, *phead;
3253 struct __queue *queue = &(pmlmepriv->scanned_queue);
3254 struct wlan_network *pnetwork = NULL;
3255 u8 blnMatch = 0;
3256 u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = {0x00};
3257 uint dev_len = 0;
3258 u8 dev_name_str[WPS_MAX_DEVICE_NAME_LEN + 5] = {0x00}; /* +5 is for the str "devN=", we have to clear it at wrqu->data.pointer */
3259
3260 /* Commented by Albert 20121225 */
3261 /* The input data is the MAC address which the application wants to know its device name. */
3262 /* Such user interface could show peer device's device name instead of ssid. */
3263 /* Format: iwpriv wlanx p2p_get2 devN = 00:E0:4C:00:00:05 */
3264
3265 DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
3266 if (copy_from_user(peerMACStr, wrqu->data.pointer + 5, 17))
3267 return -EFAULT;
3268
3269 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3270 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
3271
3272 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3273
3274 phead = get_list_head(queue);
3275 plist = phead->next;
3276
3277 while (phead != plist) {
3278 pnetwork = container_of(plist, struct wlan_network, list);
3279 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3280 u8 *wpsie;
3281 uint wpsie_len = 0;
3282
3283 /* The mac address is matched. */
3284 wpsie = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &wpsie_len);
3285 if (wpsie) {
3286 rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len);
3287 if (dev_len) {
3288 sprintf(dev_name_str, "\n\nN=%s", dev_name);
3289 blnMatch = 1;
3290 }
3291 }
3292 break;
3293 }
3294
3295 plist = plist->next;
3296 }
3297
3298 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3299
3300 if (!blnMatch)
3301 sprintf(dev_name_str, "\n\nN=0000");
3302
3303 if (copy_to_user(wrqu->data.pointer, dev_name_str, 5 + ((dev_len > 17) ? dev_len : 17)))
3304 return -EFAULT;
3305 return ret;
3306 }
3307
3308 static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
3309 struct iw_request_info *info,
3310 union iwreq_data *wrqu, char *extra)
3311 {
3312 int ret = 0;
3313 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3314 u8 peerMAC[ETH_ALEN] = {0x00};
3315 int jj, kk;
3316 u8 peerMACStr[17] = {0x00};
3317 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3318 struct list_head *plist, *phead;
3319 struct __queue *queue = &(pmlmepriv->scanned_queue);
3320 struct wlan_network *pnetwork = NULL;
3321 u8 blnMatch = 0;
3322 u8 *p2pie;
3323 uint p2pielen = 0, attr_contentlen = 0;
3324 u8 attr_content[2] = {0x00};
3325
3326 u8 inv_proc_str[17 + 8] = {0x00};
3327 /* +8 is for the str "InvProc=", we have to clear it at wrqu->data.pointer */
3328
3329 /* Commented by Ouden 20121226 */
3330 /* The application wants to know P2P initiation procedure is supported or not. */
3331 /* Format: iwpriv wlanx p2p_get2 InvProc = 00:E0:4C:00:00:05 */
3332
3333 DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
3334 if (copy_from_user(peerMACStr, wrqu->data.pointer + 8, 17))
3335 return -EFAULT;
3336
3337 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3338 peerMAC[jj] = key_2char2num(peerMACStr[kk], peerMACStr[kk + 1]);
3339
3340 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3341
3342 phead = get_list_head(queue);
3343 plist = phead->next;
3344
3345 while (phead != plist) {
3346 pnetwork = container_of(plist, struct wlan_network, list);
3347 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3348 /* Commented by Albert 20121226 */
3349 /* Match the device address located in the P2P IE */
3350 /* This is for the case that the P2P device address is not the same as the P2P interface address. */
3351
3352 p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
3353 if (p2pie) {
3354 while (p2pie) {
3355 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_CAPABILITY, attr_content, &attr_contentlen)) {
3356 /* Handle the P2P capability attribute */
3357 blnMatch = 1;
3358 break;
3359 }
3360
3361 /* Get the next P2P IE */
3362 p2pie = rtw_get_p2p_ie(p2pie+p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
3363 }
3364 }
3365 }
3366 plist = plist->next;
3367 }
3368
3369 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3370
3371 if (!blnMatch) {
3372 sprintf(inv_proc_str, "\nIP=-1");
3373 } else {
3374 if (attr_content[0] & 0x20)
3375 sprintf(inv_proc_str, "\nIP=1");
3376 else
3377 sprintf(inv_proc_str, "\nIP=0");
3378 }
3379 if (copy_to_user(wrqu->data.pointer, inv_proc_str, 8 + 17))
3380 return -EFAULT;
3381 return ret;
3382 }
3383
3384 static int rtw_p2p_connect(struct net_device *dev,
3385 struct iw_request_info *info,
3386 union iwreq_data *wrqu, char *extra)
3387 {
3388 int ret = 0;
3389 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3390 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3391 u8 peerMAC[ETH_ALEN] = {0x00};
3392 int jj, kk;
3393 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3394 struct list_head *plist, *phead;
3395 struct __queue *queue = &(pmlmepriv->scanned_queue);
3396 struct wlan_network *pnetwork = NULL;
3397 uint uintPeerChannel = 0;
3398
3399 /* Commented by Albert 20110304 */
3400 /* The input data contains two informations. */
3401 /* 1. First information is the MAC address which wants to formate with */
3402 /* 2. Second information is the WPS PINCode or "pbc" string for push button method */
3403 /* Format: 00:E0:4C:00:00:05 */
3404 /* Format: 00:E0:4C:00:00:05 */
3405
3406 DBG_88E("[%s] data = %s\n", __func__, extra);
3407
3408 if (pwdinfo->p2p_state == P2P_STATE_NONE) {
3409 DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
3410 return ret;
3411 }
3412
3413 if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO)
3414 return -1;
3415
3416 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3417 peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
3418
3419 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3420
3421 phead = get_list_head(queue);
3422 plist = phead->next;
3423
3424 while (phead != plist) {
3425 pnetwork = container_of(plist, struct wlan_network, list);
3426 if (!memcmp(pnetwork->network.MacAddress, peerMAC, ETH_ALEN)) {
3427 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
3428 break;
3429 }
3430
3431 plist = plist->next;
3432 }
3433
3434 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3435
3436 if (uintPeerChannel) {
3437 memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
3438 memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
3439
3440 pwdinfo->nego_req_info.peer_channel_num[0] = uintPeerChannel;
3441 memcpy(pwdinfo->nego_req_info.peerDevAddr, pnetwork->network.MacAddress, ETH_ALEN);
3442 pwdinfo->nego_req_info.benable = true;
3443
3444 _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
3445 if (rtw_p2p_state(pwdinfo) != P2P_STATE_GONEGO_OK) {
3446 /* Restore to the listen state if the current p2p state is not nego OK */
3447 rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
3448 }
3449
3450 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3451 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
3452
3453 DBG_88E("[%s] Start PreTx Procedure!\n", __func__);
3454 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3455 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_GO_NEGO_TIMEOUT);
3456 } else {
3457 DBG_88E("[%s] Not Found in Scanning Queue~\n", __func__);
3458 ret = -1;
3459 }
3460 return ret;
3461 }
3462
3463 static int rtw_p2p_invite_req(struct net_device *dev,
3464 struct iw_request_info *info,
3465 union iwreq_data *wrqu, char *extra)
3466 {
3467 int ret = 0;
3468 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3469 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3470 int jj, kk;
3471 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3472 struct list_head *plist, *phead;
3473 struct __queue *queue = &(pmlmepriv->scanned_queue);
3474 struct wlan_network *pnetwork = NULL;
3475 uint uintPeerChannel = 0;
3476 u8 attr_content[50] = {0x00};
3477 u8 *p2pie;
3478 uint p2pielen = 0, attr_contentlen = 0;
3479 struct tx_invite_req_info *pinvite_req_info = &pwdinfo->invitereq_info;
3480
3481 /* The input data contains two informations. */
3482 /* 1. First information is the P2P device address which you want to send to. */
3483 /* 2. Second information is the group id which combines with GO's mac address, space and GO's ssid. */
3484 /* Command line sample: iwpriv wlan0 p2p_set invite="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */
3485 /* Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy */
3486
3487 DBG_88E("[%s] data = %s\n", __func__, extra);
3488
3489 if (wrqu->data.length <= 37) {
3490 DBG_88E("[%s] Wrong format!\n", __func__);
3491 return ret;
3492 }
3493
3494 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
3495 DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
3496 return ret;
3497 } else {
3498 /* Reset the content of struct tx_invite_req_info */
3499 pinvite_req_info->benable = false;
3500 memset(pinvite_req_info->go_bssid, 0x00, ETH_ALEN);
3501 memset(pinvite_req_info->go_ssid, 0x00, WLAN_SSID_MAXLEN);
3502 pinvite_req_info->ssidlen = 0x00;
3503 pinvite_req_info->operating_ch = pwdinfo->operating_channel;
3504 memset(pinvite_req_info->peer_macaddr, 0x00, ETH_ALEN);
3505 pinvite_req_info->token = 3;
3506 }
3507
3508 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3509 pinvite_req_info->peer_macaddr[jj] = key_2char2num(extra[kk], extra[kk + 1]);
3510
3511 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3512
3513 phead = get_list_head(queue);
3514 plist = phead->next;
3515
3516 while (phead != plist) {
3517 pnetwork = container_of(plist, struct wlan_network, list);
3518
3519 /* Commented by Albert 2011/05/18 */
3520 /* Match the device address located in the P2P IE */
3521 /* This is for the case that the P2P device address is not the same as the P2P interface address. */
3522
3523 p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
3524 if (p2pie) {
3525 /* The P2P Device ID attribute is included in the Beacon frame. */
3526 /* The P2P Device Info attribute is included in the probe response frame. */
3527
3528 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
3529 /* Handle the P2P Device ID attribute of Beacon first */
3530 if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
3531 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
3532 break;
3533 }
3534 } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
3535 /* Handle the P2P Device Info attribute of probe response */
3536 if (!memcmp(attr_content, pinvite_req_info->peer_macaddr, ETH_ALEN)) {
3537 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
3538 break;
3539 }
3540 }
3541 }
3542 plist = plist->next;
3543 }
3544
3545 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3546
3547 if (uintPeerChannel) {
3548 /* Store the GO's bssid */
3549 for (jj = 0, kk = 18; jj < ETH_ALEN; jj++, kk += 3)
3550 pinvite_req_info->go_bssid[jj] = key_2char2num(extra[kk], extra[kk + 1]);
3551
3552 /* Store the GO's ssid */
3553 pinvite_req_info->ssidlen = wrqu->data.length - 36;
3554 memcpy(pinvite_req_info->go_ssid, &extra[36], (u32) pinvite_req_info->ssidlen);
3555 pinvite_req_info->benable = true;
3556 pinvite_req_info->peer_ch = uintPeerChannel;
3557
3558 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3559 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INVITE_REQ);
3560
3561 set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
3562
3563 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3564
3565 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_INVITE_TIMEOUT);
3566 } else {
3567 DBG_88E("[%s] NOT Found in the Scanning Queue!\n", __func__);
3568 }
3569 return ret;
3570 }
3571
3572 static int rtw_p2p_set_persistent(struct net_device *dev,
3573 struct iw_request_info *info,
3574 union iwreq_data *wrqu, char *extra)
3575 {
3576 int ret = 0;
3577 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3578 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3579
3580 /* The input data is 0 or 1 */
3581 /* 0: disable persistent group functionality */
3582 /* 1: enable persistent group founctionality */
3583
3584 DBG_88E("[%s] data = %s\n", __func__, extra);
3585
3586 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
3587 DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
3588 return ret;
3589 } else {
3590 if (extra[0] == '0') /* Disable the persistent group function. */
3591 pwdinfo->persistent_supported = false;
3592 else if (extra[0] == '1') /* Enable the persistent group function. */
3593 pwdinfo->persistent_supported = true;
3594 else
3595 pwdinfo->persistent_supported = false;
3596 }
3597 pr_info("[%s] persistent_supported = %d\n", __func__, pwdinfo->persistent_supported);
3598 return ret;
3599 }
3600
3601 static int rtw_p2p_prov_disc(struct net_device *dev,
3602 struct iw_request_info *info,
3603 union iwreq_data *wrqu, char *extra)
3604 {
3605 int ret = 0;
3606 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3607 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3608 u8 peerMAC[ETH_ALEN] = {0x00};
3609 int jj, kk;
3610 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3611 struct list_head *plist, *phead;
3612 struct __queue *queue = &(pmlmepriv->scanned_queue);
3613 struct wlan_network *pnetwork = NULL;
3614 uint uintPeerChannel = 0;
3615 u8 attr_content[100] = {0x00};
3616 u8 *p2pie;
3617 uint p2pielen = 0, attr_contentlen = 0;
3618
3619 /* The input data contains two informations. */
3620 /* 1. First information is the MAC address which wants to issue the provisioning discovery request frame. */
3621 /* 2. Second information is the WPS configuration method which wants to discovery */
3622 /* Format: 00:E0:4C:00:00:05_display */
3623 /* Format: 00:E0:4C:00:00:05_keypad */
3624 /* Format: 00:E0:4C:00:00:05_pbc */
3625 /* Format: 00:E0:4C:00:00:05_label */
3626
3627 DBG_88E("[%s] data = %s\n", __func__, extra);
3628
3629 if (pwdinfo->p2p_state == P2P_STATE_NONE) {
3630 DBG_88E("[%s] WiFi Direct is disable!\n", __func__);
3631 return ret;
3632 } else {
3633 /* Reset the content of struct tx_provdisc_req_info excluded the wps_config_method_request. */
3634 memset(pwdinfo->tx_prov_disc_info.peerDevAddr, 0x00, ETH_ALEN);
3635 memset(pwdinfo->tx_prov_disc_info.peerIFAddr, 0x00, ETH_ALEN);
3636 memset(&pwdinfo->tx_prov_disc_info.ssid, 0x00, sizeof(struct ndis_802_11_ssid));
3637 pwdinfo->tx_prov_disc_info.peer_channel_num[0] = 0;
3638 pwdinfo->tx_prov_disc_info.peer_channel_num[1] = 0;
3639 pwdinfo->tx_prov_disc_info.benable = false;
3640 }
3641
3642 for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
3643 peerMAC[jj] = key_2char2num(extra[kk], extra[kk + 1]);
3644
3645 if (!memcmp(&extra[18], "display", 7)) {
3646 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA;
3647 } else if (!memcmp(&extra[18], "keypad", 7)) {
3648 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD;
3649 } else if (!memcmp(&extra[18], "pbc", 3)) {
3650 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
3651 } else if (!memcmp(&extra[18], "label", 5)) {
3652 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL;
3653 } else {
3654 DBG_88E("[%s] Unknown WPS config methodn", __func__);
3655 return ret;
3656 }
3657
3658 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3659
3660 phead = get_list_head(queue);
3661 plist = phead->next;
3662
3663 while (phead != plist) {
3664
3665 if (uintPeerChannel != 0)
3666 break;
3667
3668 pnetwork = container_of(plist, struct wlan_network, list);
3669
3670 /* Commented by Albert 2011/05/18 */
3671 /* Match the device address located in the P2P IE */
3672 /* This is for the case that the P2P device address is not the same as the P2P interface address. */
3673
3674 p2pie = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength - 12, NULL, &p2pielen);
3675 if (p2pie) {
3676 while (p2pie) {
3677 /* The P2P Device ID attribute is included in the Beacon frame. */
3678 /* The P2P Device Info attribute is included in the probe response frame. */
3679
3680 if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_ID, attr_content, &attr_contentlen)) {
3681 /* Handle the P2P Device ID attribute of Beacon first */
3682 if (!memcmp(attr_content, peerMAC, ETH_ALEN)) {
3683 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
3684 break;
3685 }
3686 } else if (rtw_get_p2p_attr_content(p2pie, p2pielen, P2P_ATTR_DEVICE_INFO, attr_content, &attr_contentlen)) {
3687 /* Handle the P2P Device Info attribute of probe response */
3688 if (!memcmp(attr_content, peerMAC, ETH_ALEN)) {
3689 uintPeerChannel = pnetwork->network.Configuration.DSConfig;
3690 break;
3691 }
3692 }
3693
3694 /* Get the next P2P IE */
3695 p2pie = rtw_get_p2p_ie(p2pie+p2pielen, pnetwork->network.IELength - 12 - (p2pie - &pnetwork->network.IEs[12] + p2pielen), NULL, &p2pielen);
3696 }
3697 }
3698
3699 plist = plist->next;
3700 }
3701
3702 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
3703
3704 if (uintPeerChannel) {
3705 DBG_88E("[%s] peer channel: %d!\n", __func__, uintPeerChannel);
3706 memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, pnetwork->network.MacAddress, ETH_ALEN);
3707 memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, peerMAC, ETH_ALEN);
3708 pwdinfo->tx_prov_disc_info.peer_channel_num[0] = (u16) uintPeerChannel;
3709 pwdinfo->tx_prov_disc_info.benable = true;
3710 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3711 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ);
3712
3713 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
3714 memcpy(&pwdinfo->tx_prov_disc_info.ssid, &pnetwork->network.Ssid, sizeof(struct ndis_802_11_ssid));
3715 } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
3716 memcpy(pwdinfo->tx_prov_disc_info.ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
3717 pwdinfo->tx_prov_disc_info.ssid.SsidLength = P2P_WILDCARD_SSID_LEN;
3718 }
3719
3720 set_channel_bwmode(padapter, uintPeerChannel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
3721
3722 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3723
3724 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
3725 } else {
3726 DBG_88E("[%s] NOT Found in the Scanning Queue!\n", __func__);
3727 }
3728 return ret;
3729 }
3730
3731 /* This function is used to inform the driver the user had specified the pin code value or pbc */
3732 /* to application. */
3733
3734 static int rtw_p2p_got_wpsinfo(struct net_device *dev,
3735 struct iw_request_info *info,
3736 union iwreq_data *wrqu, char *extra)
3737 {
3738 int ret = 0;
3739 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3740 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3741
3742 DBG_88E("[%s] data = %s\n", __func__, extra);
3743 /* Added by Albert 20110328 */
3744 /* if the input data is P2P_NO_WPSINFO -> reset the wpsinfo */
3745 /* if the input data is P2P_GOT_WPSINFO_PEER_DISPLAY_PIN -> the utility just input the PIN code got from the peer P2P device. */
3746 /* if the input data is P2P_GOT_WPSINFO_SELF_DISPLAY_PIN -> the utility just got the PIN code from itself. */
3747 /* if the input data is P2P_GOT_WPSINFO_PBC -> the utility just determine to use the PBC */
3748
3749 if (*extra == '0')
3750 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
3751 else if (*extra == '1')
3752 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PEER_DISPLAY_PIN;
3753 else if (*extra == '2')
3754 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_SELF_DISPLAY_PIN;
3755 else if (*extra == '3')
3756 pwdinfo->ui_got_wps_info = P2P_GOT_WPSINFO_PBC;
3757 else
3758 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
3759 return ret;
3760 }
3761
3762 #endif /* CONFIG_88EU_P2P */
3763
3764 static int rtw_p2p_set(struct net_device *dev,
3765 struct iw_request_info *info,
3766 union iwreq_data *wrqu, char *extra)
3767 {
3768 int ret = 0;
3769
3770 #ifdef CONFIG_88EU_P2P
3771 DBG_88E("[%s] extra = %s\n", __func__, extra);
3772 if (!memcmp(extra, "enable=", 7)) {
3773 rtw_wext_p2p_enable(dev, info, wrqu, &extra[7]);
3774 } else if (!memcmp(extra, "setDN=", 6)) {
3775 wrqu->data.length -= 6;
3776 rtw_p2p_setDN(dev, info, wrqu, &extra[6]);
3777 } else if (!memcmp(extra, "profilefound=", 13)) {
3778 wrqu->data.length -= 13;
3779 rtw_p2p_profilefound(dev, info, wrqu, &extra[13]);
3780 } else if (!memcmp(extra, "prov_disc=", 10)) {
3781 wrqu->data.length -= 10;
3782 rtw_p2p_prov_disc(dev, info, wrqu, &extra[10]);
3783 } else if (!memcmp(extra, "nego=", 5)) {
3784 wrqu->data.length -= 5;
3785 rtw_p2p_connect(dev, info, wrqu, &extra[5]);
3786 } else if (!memcmp(extra, "intent=", 7)) {
3787 /* Commented by Albert 2011/03/23 */
3788 /* The wrqu->data.length will include the null character */
3789 /* So, we will decrease 7 + 1 */
3790 wrqu->data.length -= 8;
3791 rtw_p2p_set_intent(dev, info, wrqu, &extra[7]);
3792 } else if (!memcmp(extra, "ssid=", 5)) {
3793 wrqu->data.length -= 5;
3794 rtw_p2p_set_go_nego_ssid(dev, info, wrqu, &extra[5]);
3795 } else if (!memcmp(extra, "got_wpsinfo=", 12)) {
3796 wrqu->data.length -= 12;
3797 rtw_p2p_got_wpsinfo(dev, info, wrqu, &extra[12]);
3798 } else if (!memcmp(extra, "listen_ch=", 10)) {
3799 /* Commented by Albert 2011/05/24 */
3800 /* The wrqu->data.length will include the null character */
3801 /* So, we will decrease (10 + 1) */
3802 wrqu->data.length -= 11;
3803 rtw_p2p_set_listen_ch(dev, info, wrqu, &extra[10]);
3804 } else if (!memcmp(extra, "op_ch=", 6)) {
3805 /* Commented by Albert 2011/05/24 */
3806 /* The wrqu->data.length will include the null character */
3807 /* So, we will decrease (6 + 1) */
3808 wrqu->data.length -= 7;
3809 rtw_p2p_set_op_ch(dev, info, wrqu, &extra[6]);
3810 } else if (!memcmp(extra, "invite=", 7)) {
3811 wrqu->data.length -= 8;
3812 rtw_p2p_invite_req(dev, info, wrqu, &extra[7]);
3813 } else if (!memcmp(extra, "persistent=", 11)) {
3814 wrqu->data.length -= 11;
3815 rtw_p2p_set_persistent(dev, info, wrqu, &extra[11]);
3816 }
3817 #endif /* CONFIG_88EU_P2P */
3818
3819 return ret;
3820 }
3821
3822 static int rtw_p2p_get(struct net_device *dev,
3823 struct iw_request_info *info,
3824 union iwreq_data *wrqu, char *extra)
3825 {
3826 int ret = 0;
3827
3828 #ifdef CONFIG_88EU_P2P
3829 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3830
3831 if (padapter->bShowGetP2PState)
3832 DBG_88E("[%s] extra = %s\n", __func__,
3833 (char __user *)wrqu->data.pointer);
3834 if (!memcmp((__force const char *)wrqu->data.pointer,
3835 "status", 6)) {
3836 rtw_p2p_get_status(dev, info, wrqu, extra);
3837 } else if (!memcmp((__force const char *)wrqu->data.pointer,
3838 "role", 4)) {
3839 rtw_p2p_get_role(dev, info, wrqu, extra);
3840 } else if (!memcmp((__force const char *)wrqu->data.pointer,
3841 "peer_ifa", 8)) {
3842 rtw_p2p_get_peer_ifaddr(dev, info, wrqu, extra);
3843 } else if (!memcmp((__force const char *)wrqu->data.pointer,
3844 "req_cm", 6)) {
3845 rtw_p2p_get_req_cm(dev, info, wrqu, extra);
3846 } else if (!memcmp((__force const char *)wrqu->data.pointer,
3847 "peer_deva", 9)) {
3848 /* Get the P2P device address when receiving the provision discovery request frame. */
3849 rtw_p2p_get_peer_devaddr(dev, info, wrqu, extra);
3850 } else if (!memcmp((__force const char *)wrqu->data.pointer,
3851 "group_id", 8)) {
3852 rtw_p2p_get_groupid(dev, info, wrqu, extra);
3853 } else if (!memcmp((__force const char *)wrqu->data.pointer,
3854 "peer_deva_inv", 13)) {
3855 /* Get the P2P device address when receiving the P2P Invitation request frame. */
3856 rtw_p2p_get_peer_devaddr_by_invitation(dev, info, wrqu, extra);
3857 } else if (!memcmp((__force const char *)wrqu->data.pointer,
3858 "op_ch", 5)) {
3859 rtw_p2p_get_op_ch(dev, info, wrqu, extra);
3860 }
3861 #endif /* CONFIG_88EU_P2P */
3862 return ret;
3863 }
3864
3865 static int rtw_p2p_get2(struct net_device *dev,
3866 struct iw_request_info *info,
3867 union iwreq_data *wrqu, char *extra)
3868 {
3869 int ret = 0;
3870
3871 #ifdef CONFIG_88EU_P2P
3872 DBG_88E("[%s] extra = %s\n", __func__,
3873 (char __user *)wrqu->data.pointer);
3874 if (!memcmp(extra, "wpsCM =", 6)) {
3875 wrqu->data.length -= 6;
3876 rtw_p2p_get_wps_configmethod(dev, info, wrqu, &extra[6]);
3877 } else if (!memcmp(extra, "devN =", 5)) {
3878 wrqu->data.length -= 5;
3879 rtw_p2p_get_device_name(dev, info, wrqu, &extra[5]);
3880 } else if (!memcmp(extra, "dev_type =", 9)) {
3881 wrqu->data.length -= 9;
3882 rtw_p2p_get_device_type(dev, info, wrqu, &extra[9]);
3883 } else if (!memcmp(extra, "go_devadd =", 10)) {
3884 wrqu->data.length -= 10;
3885 rtw_p2p_get_go_device_address(dev, info, wrqu, &extra[10]);
3886 } else if (!memcmp(extra, "InvProc =", 8)) {
3887 wrqu->data.length -= 8;
3888 rtw_p2p_get_invitation_procedure(dev, info, wrqu, &extra[8]);
3889 }
3890
3891 #endif /* CONFIG_88EU_P2P */
3892
3893 return ret;
3894 }
3895
3896 static int rtw_cta_test_start(struct net_device *dev,
3897 struct iw_request_info *info,
3898 union iwreq_data *wrqu, char *extra)
3899 {
3900 int ret = 0;
3901 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3902 DBG_88E("%s %s\n", __func__, extra);
3903 if (!strcmp(extra, "1"))
3904 padapter->in_cta_test = 1;
3905 else
3906 padapter->in_cta_test = 0;
3907
3908 if (padapter->in_cta_test) {
3909 u32 v = usb_read32(padapter, REG_RCR);
3910 v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/* RCR_ADF */
3911 usb_write32(padapter, REG_RCR, v);
3912 DBG_88E("enable RCR_ADF\n");
3913 } else {
3914 u32 v = usb_read32(padapter, REG_RCR);
3915 v |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;/* RCR_ADF */
3916 usb_write32(padapter, REG_RCR, v);
3917 DBG_88E("disable RCR_ADF\n");
3918 }
3919 return ret;
3920 }
3921
3922 static int rtw_rereg_nd_name(struct net_device *dev,
3923 struct iw_request_info *info,
3924 union iwreq_data *wrqu, char *extra)
3925 {
3926 int ret = 0;
3927 struct adapter *padapter = rtw_netdev_priv(dev);
3928 struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv;
3929 char new_ifname[IFNAMSIZ];
3930
3931 if (rereg_priv->old_ifname[0] == 0) {
3932 char *reg_ifname;
3933 reg_ifname = padapter->registrypriv.if2name;
3934
3935 strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ);
3936 rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
3937 }
3938
3939 if (wrqu->data.length > IFNAMSIZ)
3940 return -EFAULT;
3941
3942 if (copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ))
3943 return -EFAULT;
3944
3945 if (0 == strcmp(rereg_priv->old_ifname, new_ifname))
3946 return ret;
3947
3948 DBG_88E("%s new_ifname:%s\n", __func__, new_ifname);
3949 ret = rtw_change_ifname(padapter, new_ifname);
3950 if (0 != ret)
3951 goto exit;
3952
3953 if (!memcmp(rereg_priv->old_ifname, "disable%d", 9)) {
3954 padapter->ledpriv.bRegUseLed = rereg_priv->old_bRegUseLed;
3955 rtw_hal_sw_led_init(padapter);
3956 rtw_ips_mode_req(&padapter->pwrctrlpriv, rereg_priv->old_ips_mode);
3957 }
3958
3959 strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
3960 rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
3961
3962 if (!memcmp(new_ifname, "disable%d", 9)) {
3963 DBG_88E("%s disable\n", __func__);
3964 /* free network queue for Android's timming issue */
3965 rtw_free_network_queue(padapter, true);
3966
3967 /* close led */
3968 rtw_led_control(padapter, LED_CTL_POWER_OFF);
3969 rereg_priv->old_bRegUseLed = padapter->ledpriv.bRegUseLed;
3970 padapter->ledpriv.bRegUseLed = false;
3971 rtw_hal_sw_led_deinit(padapter);
3972
3973 /* the interface is being "disabled", we can do deeper IPS */
3974 rereg_priv->old_ips_mode = rtw_get_ips_mode_req(&padapter->pwrctrlpriv);
3975 rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL);
3976 }
3977 exit:
3978 return ret;
3979 }
3980
3981 static void mac_reg_dump(struct adapter *padapter)
3982 {
3983 int i, j = 1;
3984 pr_info("\n ======= MAC REG =======\n");
3985 for (i = 0x0; i < 0x300; i += 4) {
3986 if (j%4 == 1)
3987 pr_info("0x%02x", i);
3988 pr_info(" 0x%08x ", usb_read32(padapter, i));
3989 if ((j++)%4 == 0)
3990 pr_info("\n");
3991 }
3992 for (i = 0x400; i < 0x800; i += 4) {
3993 if (j%4 == 1)
3994 pr_info("0x%02x", i);
3995 pr_info(" 0x%08x ", usb_read32(padapter, i));
3996 if ((j++)%4 == 0)
3997 pr_info("\n");
3998 }
3999 }
4000
4001 static void bb_reg_dump(struct adapter *padapter)
4002 {
4003 int i, j = 1;
4004 pr_info("\n ======= BB REG =======\n");
4005 for (i = 0x800; i < 0x1000; i += 4) {
4006 if (j%4 == 1)
4007 pr_info("0x%02x", i);
4008
4009 pr_info(" 0x%08x ", usb_read32(padapter, i));
4010 if ((j++)%4 == 0)
4011 pr_info("\n");
4012 }
4013 }
4014
4015 static void rf_reg_dump(struct adapter *padapter)
4016 {
4017 int i, j = 1, path;
4018 u32 value;
4019 u8 rf_type, path_nums = 0;
4020 rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
4021
4022 pr_info("\n ======= RF REG =======\n");
4023 if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type))
4024 path_nums = 1;
4025 else
4026 path_nums = 2;
4027
4028 for (path = 0; path < path_nums; path++) {
4029 pr_info("\nRF_Path(%x)\n", path);
4030 for (i = 0; i < 0x100; i++) {
4031 value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
4032 if (j%4 == 1)
4033 pr_info("0x%02x ", i);
4034 pr_info(" 0x%08x ", value);
4035 if ((j++)%4 == 0)
4036 pr_info("\n");
4037 }
4038 }
4039 }
4040
4041 static int rtw_dbg_port(struct net_device *dev,
4042 struct iw_request_info *info,
4043 union iwreq_data *wrqu, char *extra)
4044 {
4045 int ret = 0;
4046 u8 major_cmd, minor_cmd;
4047 u16 arg;
4048 s32 extra_arg;
4049 u32 *pdata, val32;
4050 struct sta_info *psta;
4051 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4052 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4053 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4054 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4055 struct security_priv *psecuritypriv = &padapter->securitypriv;
4056 struct wlan_network *cur_network = &(pmlmepriv->cur_network);
4057 struct sta_priv *pstapriv = &padapter->stapriv;
4058
4059 pdata = (u32 *)&wrqu->data;
4060
4061 val32 = *pdata;
4062 arg = (u16)(val32 & 0x0000ffff);
4063 major_cmd = (u8)(val32 >> 24);
4064 minor_cmd = (u8)((val32 >> 16) & 0x00ff);
4065
4066 extra_arg = *(pdata+1);
4067
4068 switch (major_cmd) {
4069 case 0x70:/* read_reg */
4070 switch (minor_cmd) {
4071 case 1:
4072 DBG_88E("usb_read8(0x%x) = 0x%02x\n", arg, usb_read8(padapter, arg));
4073 break;
4074 case 2:
4075 DBG_88E("usb_read16(0x%x) = 0x%04x\n", arg, usb_read16(padapter, arg));
4076 break;
4077 case 4:
4078 DBG_88E("usb_read32(0x%x) = 0x%08x\n", arg, usb_read32(padapter, arg));
4079 break;
4080 }
4081 break;
4082 case 0x71:/* write_reg */
4083 switch (minor_cmd) {
4084 case 1:
4085 usb_write8(padapter, arg, extra_arg);
4086 DBG_88E("usb_write8(0x%x) = 0x%02x\n", arg, usb_read8(padapter, arg));
4087 break;
4088 case 2:
4089 usb_write16(padapter, arg, extra_arg);
4090 DBG_88E("usb_write16(0x%x) = 0x%04x\n", arg, usb_read16(padapter, arg));
4091 break;
4092 case 4:
4093 usb_write32(padapter, arg, extra_arg);
4094 DBG_88E("usb_write32(0x%x) = 0x%08x\n", arg, usb_read32(padapter, arg));
4095 break;
4096 }
4097 break;
4098 case 0x72:/* read_bb */
4099 DBG_88E("read_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
4100 break;
4101 case 0x73:/* write_bb */
4102 rtw_hal_write_bbreg(padapter, arg, 0xffffffff, extra_arg);
4103 DBG_88E("write_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
4104 break;
4105 case 0x74:/* read_rf */
4106 DBG_88E("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));
4107 break;
4108 case 0x75:/* write_rf */
4109 rtw_hal_write_rfreg(padapter, minor_cmd, arg, 0xffffffff, extra_arg);
4110 DBG_88E("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));
4111 break;
4112
4113 case 0x76:
4114 switch (minor_cmd) {
4115 case 0x00: /* normal mode, */
4116 padapter->recvpriv.is_signal_dbg = 0;
4117 break;
4118 case 0x01: /* dbg mode */
4119 padapter->recvpriv.is_signal_dbg = 1;
4120 extra_arg = extra_arg > 100 ? 100 : extra_arg;
4121 extra_arg = extra_arg < 0 ? 0 : extra_arg;
4122 padapter->recvpriv.signal_strength_dbg = extra_arg;
4123 break;
4124 }
4125 break;
4126 case 0x78: /* IOL test */
4127 switch (minor_cmd) {
4128 case 0x04: /* LLT table initialization test */
4129 {
4130 u8 page_boundary = 0xf9;
4131 struct xmit_frame *xmit_frame;
4132
4133 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
4134 if (xmit_frame == NULL) {
4135 ret = -ENOMEM;
4136 break;
4137 }
4138
4139 rtw_IOL_append_LLT_cmd(xmit_frame, page_boundary);
4140
4141 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 500, 0))
4142 ret = -EPERM;
4143 }
4144 break;
4145 case 0x05: /* blink LED test */
4146 {
4147 u16 reg = 0x4c;
4148 u32 blink_num = 50;
4149 u32 blink_delay_ms = 200;
4150 int i;
4151 struct xmit_frame *xmit_frame;
4152
4153 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
4154 if (xmit_frame == NULL) {
4155 ret = -ENOMEM;
4156 break;
4157 }
4158
4159 for (i = 0; i < blink_num; i++) {
4160 rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x00, 0xff);
4161 rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
4162 rtw_IOL_append_WB_cmd(xmit_frame, reg, 0x08, 0xff);
4163 rtw_IOL_append_DELAY_MS_cmd(xmit_frame, blink_delay_ms);
4164 }
4165 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, (blink_delay_ms*blink_num*2)+200, 0))
4166 ret = -EPERM;
4167 }
4168 break;
4169
4170 case 0x06: /* continuous write byte test */
4171 {
4172 u16 reg = arg;
4173 u16 start_value = 0;
4174 u32 write_num = extra_arg;
4175 int i;
4176 u8 final;
4177 struct xmit_frame *xmit_frame;
4178
4179 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
4180 if (xmit_frame == NULL) {
4181 ret = -ENOMEM;
4182 break;
4183 }
4184
4185 for (i = 0; i < write_num; i++)
4186 rtw_IOL_append_WB_cmd(xmit_frame, reg, i+start_value, 0xFF);
4187 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
4188 ret = -EPERM;
4189
4190 final = usb_read8(padapter, reg);
4191 if (start_value+write_num-1 == final)
4192 DBG_88E("continuous IOL_CMD_WB_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
4193 else
4194 DBG_88E("continuous IOL_CMD_WB_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
4195 }
4196 break;
4197
4198 case 0x07: /* continuous write word test */
4199 {
4200 u16 reg = arg;
4201 u16 start_value = 200;
4202 u32 write_num = extra_arg;
4203
4204 int i;
4205 u16 final;
4206 struct xmit_frame *xmit_frame;
4207
4208 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
4209 if (xmit_frame == NULL) {
4210 ret = -ENOMEM;
4211 break;
4212 }
4213
4214 for (i = 0; i < write_num; i++)
4215 rtw_IOL_append_WW_cmd(xmit_frame, reg, i+start_value, 0xFFFF);
4216 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
4217 ret = -EPERM;
4218
4219 final = usb_read16(padapter, reg);
4220 if (start_value+write_num-1 == final)
4221 DBG_88E("continuous IOL_CMD_WW_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
4222 else
4223 DBG_88E("continuous IOL_CMD_WW_REG to 0x%x %u times Fail, start:%u, final:%u\n", reg, write_num, start_value, final);
4224 }
4225 break;
4226 case 0x08: /* continuous write dword test */
4227 {
4228 u16 reg = arg;
4229 u32 start_value = 0x110000c7;
4230 u32 write_num = extra_arg;
4231
4232 int i;
4233 u32 final;
4234 struct xmit_frame *xmit_frame;
4235
4236 xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
4237 if (xmit_frame == NULL) {
4238 ret = -ENOMEM;
4239 break;
4240 }
4241
4242 for (i = 0; i < write_num; i++)
4243 rtw_IOL_append_WD_cmd(xmit_frame, reg, i+start_value, 0xFFFFFFFF);
4244 if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
4245 ret = -EPERM;
4246
4247 final = usb_read32(padapter, reg);
4248 if (start_value+write_num-1 == final)
4249 DBG_88E("continuous IOL_CMD_WD_REG to 0x%x %u times Success, start:%u, final:%u\n",
4250 reg, write_num, start_value, final);
4251 else
4252 DBG_88E("continuous IOL_CMD_WD_REG to 0x%x %u times Fail, start:%u, final:%u\n",
4253 reg, write_num, start_value, final);
4254 }
4255 break;
4256 }
4257 break;
4258 case 0x79:
4259 {
4260 /*
4261 * dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15
4262 * dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15
4263 */
4264 u8 value = extra_arg & 0x0f;
4265 u8 sign = minor_cmd;
4266 u16 write_value = 0;
4267
4268 DBG_88E("%s set RESP_TXAGC to %s %u\n", __func__, sign ? "minus" : "plus", value);
4269
4270 if (sign)
4271 value = value | 0x10;
4272
4273 write_value = value | (value << 5);
4274 usb_write16(padapter, 0x6d9, write_value);
4275 }
4276 break;
4277 case 0x7a:
4278 receive_disconnect(padapter, pmlmeinfo->network.MacAddress
4279 , WLAN_REASON_EXPIRATION_CHK);
4280 break;
4281 case 0x7F:
4282 switch (minor_cmd) {
4283 case 0x0:
4284 DBG_88E("fwstate = 0x%x\n", get_fwstate(pmlmepriv));
4285 break;
4286 case 0x01:
4287 DBG_88E("auth_alg = 0x%x, enc_alg = 0x%x, auth_type = 0x%x, enc_type = 0x%x\n",
4288 psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,
4289 psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus);
4290 break;
4291 case 0x02:
4292 DBG_88E("pmlmeinfo->state = 0x%x\n", pmlmeinfo->state);
4293 break;
4294 case 0x03:
4295 DBG_88E("qos_option =%d\n", pmlmepriv->qospriv.qos_option);
4296 DBG_88E("ht_option =%d\n", pmlmepriv->htpriv.ht_option);
4297 break;
4298 case 0x04:
4299 DBG_88E("cur_ch =%d\n", pmlmeext->cur_channel);
4300 DBG_88E("cur_bw =%d\n", pmlmeext->cur_bwmode);
4301 DBG_88E("cur_ch_off =%d\n", pmlmeext->cur_ch_offset);
4302 break;
4303 case 0x05:
4304 psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
4305 if (psta) {
4306 int i;
4307 struct recv_reorder_ctrl *preorder_ctrl;
4308
4309 DBG_88E("SSID =%s\n", cur_network->network.Ssid.Ssid);
4310 DBG_88E("sta's macaddr: %pM\n", psta->hwaddr);
4311 DBG_88E("cur_channel =%d, cur_bwmode =%d, cur_ch_offset =%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
4312 DBG_88E("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self);
4313 DBG_88E("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
4314 DBG_88E("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
4315 DBG_88E("bwmode =%d, ch_offset =%d, sgi =%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
4316 DBG_88E("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
4317 DBG_88E("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
4318 for (i = 0; i < 16; i++) {
4319 preorder_ctrl = &psta->recvreorder_ctrl[i];
4320 if (preorder_ctrl->enable)
4321 DBG_88E("tid =%d, indicate_seq =%d\n", i, preorder_ctrl->indicate_seq);
4322 }
4323 } else {
4324 DBG_88E("can't get sta's macaddr, cur_network's macaddr:%pM\n", (cur_network->network.MacAddress));
4325 }
4326 break;
4327 case 0x06:
4328 {
4329 u32 ODMFlag;
4330 rtw_hal_get_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
4331 DBG_88E("(B)DMFlag = 0x%x, arg = 0x%x\n", ODMFlag, arg);
4332 ODMFlag = (u32)(0x0f&arg);
4333 DBG_88E("(A)DMFlag = 0x%x\n", ODMFlag);
4334 rtw_hal_set_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
4335 }
4336 break;
4337 case 0x07:
4338 DBG_88E("bSurpriseRemoved =%d, bDriverStopped =%d\n",
4339 padapter->bSurpriseRemoved, padapter->bDriverStopped);
4340 break;
4341 case 0x08:
4342 {
4343 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
4344 struct recv_priv *precvpriv = &padapter->recvpriv;
4345
4346 DBG_88E("free_xmitbuf_cnt =%d, free_xmitframe_cnt =%d, free_xmit_extbuf_cnt =%d\n",
4347 pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt, pxmitpriv->free_xmit_extbuf_cnt);
4348 DBG_88E("rx_urb_pending_cn =%d\n", precvpriv->rx_pending_cnt);
4349 }
4350 break;
4351 case 0x09:
4352 {
4353 int i, j;
4354 struct list_head *plist, *phead;
4355 struct recv_reorder_ctrl *preorder_ctrl;
4356
4357 #ifdef CONFIG_88EU_AP_MODE
4358 DBG_88E("sta_dz_bitmap = 0x%x, tim_bitmap = 0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap);
4359 #endif
4360 spin_lock_bh(&pstapriv->sta_hash_lock);
4361
4362 for (i = 0; i < NUM_STA; i++) {
4363 phead = &(pstapriv->sta_hash[i]);
4364 plist = phead->next;
4365
4366 while (phead != plist) {
4367 psta = container_of(plist, struct sta_info, hash_list);
4368
4369 plist = plist->next;
4370
4371 if (extra_arg == psta->aid) {
4372 DBG_88E("sta's macaddr:%pM\n", (psta->hwaddr));
4373 DBG_88E("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self);
4374 DBG_88E("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
4375 DBG_88E("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
4376 DBG_88E("bwmode =%d, ch_offset =%d, sgi =%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi);
4377 DBG_88E("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
4378 DBG_88E("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
4379
4380 #ifdef CONFIG_88EU_AP_MODE
4381 DBG_88E("capability = 0x%x\n", psta->capability);
4382 DBG_88E("flags = 0x%x\n", psta->flags);
4383 DBG_88E("wpa_psk = 0x%x\n", psta->wpa_psk);
4384 DBG_88E("wpa2_group_cipher = 0x%x\n", psta->wpa2_group_cipher);
4385 DBG_88E("wpa2_pairwise_cipher = 0x%x\n", psta->wpa2_pairwise_cipher);
4386 DBG_88E("qos_info = 0x%x\n", psta->qos_info);
4387 #endif
4388 DBG_88E("dot118021XPrivacy = 0x%x\n", psta->dot118021XPrivacy);
4389
4390 for (j = 0; j < 16; j++) {
4391 preorder_ctrl = &psta->recvreorder_ctrl[j];
4392 if (preorder_ctrl->enable)
4393 DBG_88E("tid =%d, indicate_seq =%d\n", j, preorder_ctrl->indicate_seq);
4394 }
4395 }
4396 }
4397 }
4398 spin_unlock_bh(&pstapriv->sta_hash_lock);
4399 }
4400 break;
4401 case 0x0c:/* dump rx/tx packet */
4402 if (arg == 0) {
4403 DBG_88E("dump rx packet (%d)\n", extra_arg);
4404 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_RXPKT, &(extra_arg));
4405 } else if (arg == 1) {
4406 DBG_88E("dump tx packet (%d)\n", extra_arg);
4407 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(extra_arg));
4408 }
4409 break;
4410 case 0x0f:
4411 break;
4412 case 0x15:
4413 {
4414 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
4415 DBG_88E("==>silent resete cnts:%d\n", pwrpriv->ips_enter_cnts);
4416 }
4417 break;
4418 case 0x10:/* driver version display */
4419 DBG_88E("rtw driver version =%s\n", DRIVERVERSION);
4420 break;
4421 case 0x11:
4422 DBG_88E("turn %s Rx RSSI display function\n", (extra_arg == 1) ? "on" : "off");
4423 padapter->bRxRSSIDisplay = extra_arg;
4424 rtw_hal_set_def_var(padapter, HW_DEF_FA_CNT_DUMP, &extra_arg);
4425 break;
4426 case 0x12: /* set rx_stbc */
4427 {
4428 struct registry_priv *pregpriv = &padapter->registrypriv;
4429 /* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g */
4430 /* default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */
4431 if (!pregpriv)
4432 break;
4433 if (extra_arg >= 0 && extra_arg <= 3) {
4434 pregpriv->rx_stbc = extra_arg;
4435 DBG_88E("set rx_stbc =%d\n", pregpriv->rx_stbc);
4436 } else {
4437 DBG_88E("get rx_stbc =%d\n", pregpriv->rx_stbc);
4438 }
4439 }
4440 break;
4441 case 0x13: /* set ampdu_enable */
4442 {
4443 struct registry_priv *pregpriv = &padapter->registrypriv;
4444 /* 0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec) */
4445 if (!pregpriv)
4446 break;
4447 if (extra_arg >= 0 && extra_arg < 3) {
4448 pregpriv->ampdu_enable = extra_arg;
4449 DBG_88E("set ampdu_enable =%d\n", pregpriv->ampdu_enable);
4450 } else {
4451 DBG_88E("get ampdu_enable =%d\n", pregpriv->ampdu_enable);
4452 }
4453 }
4454 break;
4455 case 0x14: /* get wifi_spec */
4456 {
4457 struct registry_priv *pregpriv = &padapter->registrypriv;
4458 DBG_88E("get wifi_spec =%d\n", pregpriv->wifi_spec);
4459 }
4460 break;
4461 case 0x16:
4462 if (arg == 0xff) {
4463 pr_info("ODM_COMP_DIG\t\tBIT0\n");
4464 pr_info("ODM_COMP_RA_MASK\t\tBIT1\n");
4465 pr_info("ODM_COMP_DYNAMIC_TXPWR\tBIT2\n");
4466 pr_info("ODM_COMP_FA_CNT\t\tBIT3\n");
4467 pr_info("ODM_COMP_RSSI_MONITOR\tBIT4\n");
4468 pr_info("ODM_COMP_CCK_PD\t\tBIT5\n");
4469 pr_info("ODM_COMP_ANT_DIV\t\tBIT6\n");
4470 pr_info("ODM_COMP_PWR_SAVE\t\tBIT7\n");
4471 pr_info("ODM_COMP_PWR_TRAIN\tBIT8\n");
4472 pr_info("ODM_COMP_RATE_ADAPTIVE\tBIT9\n");
4473 pr_info("ODM_COMP_PATH_DIV\t\tBIT10\n");
4474 pr_info("ODM_COMP_PSD \tBIT11\n");
4475 pr_info("ODM_COMP_DYNAMIC_PRICCA\tBIT12\n");
4476 pr_info("ODM_COMP_RXHP\t\tBIT13\n");
4477 pr_info("ODM_COMP_EDCA_TURBO\tBIT16\n");
4478 pr_info("ODM_COMP_EARLY_MODE\tBIT17\n");
4479 pr_info("ODM_COMP_TX_PWR_TRACK\tBIT24\n");
4480 pr_info("ODM_COMP_RX_GAIN_TRACK\tBIT25\n");
4481 pr_info("ODM_COMP_CALIBRATION\tBIT26\n");
4482 rtw_hal_get_def_var(padapter, HW_DEF_ODM_DBG_FLAG, &extra_arg);
4483 } else {
4484 rtw_hal_set_def_var(padapter, HW_DEF_ODM_DBG_FLAG, &extra_arg);
4485 }
4486 break;
4487 case 0x23:
4488 DBG_88E("turn %s the bNotifyChannelChange Variable\n", (extra_arg == 1) ? "on" : "off");
4489 padapter->bNotifyChannelChange = extra_arg;
4490 break;
4491 case 0x24:
4492 #ifdef CONFIG_88EU_P2P
4493 DBG_88E("turn %s the bShowGetP2PState Variable\n", (extra_arg == 1) ? "on" : "off");
4494 padapter->bShowGetP2PState = extra_arg;
4495 #endif /* CONFIG_88EU_P2P */
4496 break;
4497 case 0xaa:
4498 if (extra_arg > 0x13)
4499 extra_arg = 0xFF;
4500 DBG_88E("chang data rate to :0x%02x\n", extra_arg);
4501 padapter->fix_rate = extra_arg;
4502 break;
4503 case 0xdd:/* registers dump, 0 for mac reg, 1 for bb reg, 2 for rf reg */
4504 if (extra_arg == 0)
4505 mac_reg_dump(padapter);
4506 else if (extra_arg == 1)
4507 bb_reg_dump(padapter);
4508 else if (extra_arg == 2)
4509 rf_reg_dump(padapter);
4510 break;
4511 case 0xee:/* turn on/off dynamic funcs */
4512 {
4513 u32 odm_flag;
4514
4515 if (0xf == extra_arg) {
4516 rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag);
4517 DBG_88E(" === DMFlag(0x%08x) ===\n", odm_flag);
4518 DBG_88E("extra_arg = 0 - disable all dynamic func\n");
4519 DBG_88E("extra_arg = 1 - disable DIG- BIT(0)\n");
4520 DBG_88E("extra_arg = 2 - disable High power - BIT(1)\n");
4521 DBG_88E("extra_arg = 3 - disable tx power tracking - BIT(2)\n");
4522 DBG_88E("extra_arg = 4 - disable BT coexistence - BIT(3)\n");
4523 DBG_88E("extra_arg = 5 - disable antenna diversity - BIT(4)\n");
4524 DBG_88E("extra_arg = 6 - enable all dynamic func\n");
4525 } else {
4526 /* extra_arg = 0 - disable all dynamic func
4527 extra_arg = 1 - disable DIG
4528 extra_arg = 2 - disable tx power tracking
4529 extra_arg = 3 - turn on all dynamic func
4530 */
4531 rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &(extra_arg));
4532 rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &odm_flag);
4533 DBG_88E(" === DMFlag(0x%08x) ===\n", odm_flag);
4534 }
4535 }
4536 break;
4537
4538 case 0xfd:
4539 usb_write8(padapter, 0xc50, arg);
4540 DBG_88E("wr(0xc50) = 0x%x\n", usb_read8(padapter, 0xc50));
4541 usb_write8(padapter, 0xc58, arg);
4542 DBG_88E("wr(0xc58) = 0x%x\n", usb_read8(padapter, 0xc58));
4543 break;
4544 case 0xfe:
4545 DBG_88E("rd(0xc50) = 0x%x\n", usb_read8(padapter, 0xc50));
4546 DBG_88E("rd(0xc58) = 0x%x\n", usb_read8(padapter, 0xc58));
4547 break;
4548 case 0xff:
4549 DBG_88E("dbg(0x210) = 0x%x\n", usb_read32(padapter, 0x210));
4550 DBG_88E("dbg(0x608) = 0x%x\n", usb_read32(padapter, 0x608));
4551 DBG_88E("dbg(0x280) = 0x%x\n", usb_read32(padapter, 0x280));
4552 DBG_88E("dbg(0x284) = 0x%x\n", usb_read32(padapter, 0x284));
4553 DBG_88E("dbg(0x288) = 0x%x\n", usb_read32(padapter, 0x288));
4554
4555 DBG_88E("dbg(0x664) = 0x%x\n", usb_read32(padapter, 0x664));
4556
4557 DBG_88E("\n");
4558
4559 DBG_88E("dbg(0x430) = 0x%x\n", usb_read32(padapter, 0x430));
4560 DBG_88E("dbg(0x438) = 0x%x\n", usb_read32(padapter, 0x438));
4561
4562 DBG_88E("dbg(0x440) = 0x%x\n", usb_read32(padapter, 0x440));
4563
4564 DBG_88E("dbg(0x458) = 0x%x\n", usb_read32(padapter, 0x458));
4565
4566 DBG_88E("dbg(0x484) = 0x%x\n", usb_read32(padapter, 0x484));
4567 DBG_88E("dbg(0x488) = 0x%x\n", usb_read32(padapter, 0x488));
4568
4569 DBG_88E("dbg(0x444) = 0x%x\n", usb_read32(padapter, 0x444));
4570 DBG_88E("dbg(0x448) = 0x%x\n", usb_read32(padapter, 0x448));
4571 DBG_88E("dbg(0x44c) = 0x%x\n", usb_read32(padapter, 0x44c));
4572 DBG_88E("dbg(0x450) = 0x%x\n", usb_read32(padapter, 0x450));
4573 break;
4574 }
4575 break;
4576 default:
4577 DBG_88E("error dbg cmd!\n");
4578 break;
4579 }
4580 return ret;
4581 }
4582
4583 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
4584 {
4585 uint ret = 0;
4586 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4587
4588 switch (name) {
4589 case IEEE_PARAM_WPA_ENABLED:
4590 padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
4591 switch ((value)&0xff) {
4592 case 1: /* WPA */
4593 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
4594 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
4595 break;
4596 case 2: /* WPA2 */
4597 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
4598 padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
4599 break;
4600 }
4601 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
4602 ("wpa_set_param:padapter->securitypriv.ndisauthtype =%d\n", padapter->securitypriv.ndisauthtype));
4603 break;
4604 case IEEE_PARAM_TKIP_COUNTERMEASURES:
4605 break;
4606 case IEEE_PARAM_DROP_UNENCRYPTED: {
4607 /* HACK:
4608 *
4609 * wpa_supplicant calls set_wpa_enabled when the driver
4610 * is loaded and unloaded, regardless of if WPA is being
4611 * used. No other calls are made which can be used to
4612 * determine if encryption will be used or not prior to
4613 * association being expected. If encryption is not being
4614 * used, drop_unencrypted is set to false, else true -- we
4615 * can use this to determine if the CAP_PRIVACY_ON bit should
4616 * be set.
4617 */
4618
4619 break;
4620 }
4621 case IEEE_PARAM_PRIVACY_INVOKED:
4622 break;
4623
4624 case IEEE_PARAM_AUTH_ALGS:
4625 ret = wpa_set_auth_algs(dev, value);
4626 break;
4627 case IEEE_PARAM_IEEE_802_1X:
4628 break;
4629 case IEEE_PARAM_WPAX_SELECT:
4630 break;
4631 default:
4632 ret = -EOPNOTSUPP;
4633 break;
4634 }
4635 return ret;
4636 }
4637
4638 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
4639 {
4640 int ret = 0;
4641 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4642
4643 switch (command) {
4644 case IEEE_MLME_STA_DEAUTH:
4645 if (!rtw_set_802_11_disassociate(padapter))
4646 ret = -1;
4647 break;
4648 case IEEE_MLME_STA_DISASSOC:
4649 if (!rtw_set_802_11_disassociate(padapter))
4650 ret = -1;
4651 break;
4652 default:
4653 ret = -EOPNOTSUPP;
4654 break;
4655 }
4656
4657 return ret;
4658 }
4659
4660 static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
4661 {
4662 struct ieee_param *param;
4663 uint ret = 0;
4664
4665 if (p->length < sizeof(struct ieee_param) || !p->pointer) {
4666 ret = -EINVAL;
4667 goto out;
4668 }
4669
4670 param = (struct ieee_param *)rtw_malloc(p->length);
4671 if (param == NULL) {
4672 ret = -ENOMEM;
4673 goto out;
4674 }
4675
4676 if (copy_from_user(param, p->pointer, p->length)) {
4677 kfree(param);
4678 ret = -EFAULT;
4679 goto out;
4680 }
4681
4682 switch (param->cmd) {
4683 case IEEE_CMD_SET_WPA_PARAM:
4684 ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
4685 break;
4686
4687 case IEEE_CMD_SET_WPA_IE:
4688 ret = rtw_set_wpa_ie((struct adapter *)rtw_netdev_priv(dev),
4689 (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
4690 break;
4691
4692 case IEEE_CMD_SET_ENCRYPTION:
4693 ret = wpa_set_encryption(dev, param, p->length);
4694 break;
4695
4696 case IEEE_CMD_MLME:
4697 ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
4698 break;
4699
4700 default:
4701 DBG_88E("Unknown WPA supplicant request: %d\n", param->cmd);
4702 ret = -EOPNOTSUPP;
4703 break;
4704 }
4705
4706 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
4707 ret = -EFAULT;
4708
4709 kfree(param);
4710
4711 out:
4712
4713 return ret;
4714 }
4715
4716 #ifdef CONFIG_88EU_AP_MODE
4717 static u8 set_pairwise_key(struct adapter *padapter, struct sta_info *psta)
4718 {
4719 struct cmd_obj *ph2c;
4720 struct set_stakey_parm *psetstakey_para;
4721 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4722 u8 res = _SUCCESS;
4723
4724 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4725 if (ph2c == NULL) {
4726 res = _FAIL;
4727 goto exit;
4728 }
4729
4730 psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
4731 if (psetstakey_para == NULL) {
4732 kfree(ph2c);
4733 res = _FAIL;
4734 goto exit;
4735 }
4736
4737 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
4738
4739 psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy;
4740
4741 memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);
4742
4743 memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
4744
4745 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
4746
4747 exit:
4748
4749 return res;
4750 }
4751
4752 static int set_group_key(struct adapter *padapter, u8 *key, u8 alg, int keyid)
4753 {
4754 u8 keylen;
4755 struct cmd_obj *pcmd;
4756 struct setkey_parm *psetkeyparm;
4757 struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
4758 int res = _SUCCESS;
4759
4760 DBG_88E("%s\n", __func__);
4761
4762 pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4763 if (pcmd == NULL) {
4764 res = _FAIL;
4765 goto exit;
4766 }
4767 psetkeyparm = (struct setkey_parm *)rtw_zmalloc(sizeof(struct setkey_parm));
4768 if (psetkeyparm == NULL) {
4769 kfree(pcmd);
4770 res = _FAIL;
4771 goto exit;
4772 }
4773
4774 memset(psetkeyparm, 0, sizeof(struct setkey_parm));
4775
4776 psetkeyparm->keyid = (u8)keyid;
4777
4778 psetkeyparm->algorithm = alg;
4779
4780 psetkeyparm->set_tx = 1;
4781
4782 switch (alg) {
4783 case _WEP40_:
4784 keylen = 5;
4785 break;
4786 case _WEP104_:
4787 keylen = 13;
4788 break;
4789 case _TKIP_:
4790 case _TKIP_WTMIC_:
4791 case _AES_:
4792 default:
4793 keylen = 16;
4794 }
4795
4796 memcpy(&(psetkeyparm->key[0]), key, keylen);
4797
4798 pcmd->cmdcode = _SetKey_CMD_;
4799 pcmd->parmbuf = (u8 *)psetkeyparm;
4800 pcmd->cmdsz = (sizeof(struct setkey_parm));
4801 pcmd->rsp = NULL;
4802 pcmd->rspsz = 0;
4803
4804 _rtw_init_listhead(&pcmd->list);
4805
4806 res = rtw_enqueue_cmd(pcmdpriv, pcmd);
4807
4808 exit:
4809
4810 return res;
4811 }
4812
4813 static int set_wep_key(struct adapter *padapter, u8 *key, u8 keylen, int keyid)
4814 {
4815 u8 alg;
4816
4817 switch (keylen) {
4818 case 5:
4819 alg = _WEP40_;
4820 break;
4821 case 13:
4822 alg = _WEP104_;
4823 break;
4824 default:
4825 alg = _NO_PRIVACY_;
4826 }
4827
4828 return set_group_key(padapter, key, alg, keyid);
4829 }
4830
4831 static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
4832 {
4833 int ret = 0;
4834 u32 wep_key_idx, wep_key_len, wep_total_len;
4835 struct ndis_802_11_wep *pwep = NULL;
4836 struct sta_info *psta = NULL, *pbcmc_sta = NULL;
4837 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4838 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4839 struct security_priv *psecuritypriv = &(padapter->securitypriv);
4840 struct sta_priv *pstapriv = &padapter->stapriv;
4841
4842 DBG_88E("%s\n", __func__);
4843 param->u.crypt.err = 0;
4844 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
4845 if (param_len != sizeof(struct ieee_param) + param->u.crypt.key_len) {
4846 ret = -EINVAL;
4847 goto exit;
4848 }
4849 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
4850 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
4851 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
4852 if (param->u.crypt.idx >= WEP_KEYS) {
4853 ret = -EINVAL;
4854 goto exit;
4855 }
4856 } else {
4857 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
4858 if (!psta) {
4859 DBG_88E("rtw_set_encryption(), sta has already been removed or never been added\n");
4860 goto exit;
4861 }
4862 }
4863
4864 if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
4865 /* todo:clear default encryption keys */
4866
4867 DBG_88E("clear default encryption keys, keyid =%d\n", param->u.crypt.idx);
4868 goto exit;
4869 }
4870 if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
4871 DBG_88E("r871x_set_encryption, crypt.alg = WEP\n");
4872 wep_key_idx = param->u.crypt.idx;
4873 wep_key_len = param->u.crypt.key_len;
4874 DBG_88E("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
4875 if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
4876 ret = -EINVAL;
4877 goto exit;
4878 }
4879
4880 if (wep_key_len > 0) {
4881 wep_key_len = wep_key_len <= 5 ? 5 : 13;
4882 wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
4883 pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
4884 if (pwep == NULL) {
4885 DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n");
4886 goto exit;
4887 }
4888
4889 memset(pwep, 0, wep_total_len);
4890
4891 pwep->KeyLength = wep_key_len;
4892 pwep->Length = wep_total_len;
4893 }
4894
4895 pwep->KeyIndex = wep_key_idx;
4896
4897 memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
4898
4899 if (param->u.crypt.set_tx) {
4900 DBG_88E("wep, set_tx = 1\n");
4901
4902 psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
4903 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
4904 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
4905
4906 if (pwep->KeyLength == 13) {
4907 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
4908 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
4909 }
4910
4911 psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
4912
4913 memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
4914
4915 psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
4916
4917 set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
4918 } else {
4919 DBG_88E("wep, set_tx = 0\n");
4920
4921 /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
4922 /* psecuritypriv->dot11PrivacyKeyIndex = keyid", but can rtw_set_key to cam */
4923
4924 memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
4925
4926 psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
4927
4928 set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
4929 }
4930
4931 goto exit;
4932 }
4933
4934 if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /* group key */
4935 if (param->u.crypt.set_tx == 1) {
4936 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
4937 DBG_88E("%s, set group_key, WEP\n", __func__);
4938
4939 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
4940 param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
4941
4942 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
4943 if (param->u.crypt.key_len == 13)
4944 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
4945 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
4946 DBG_88E("%s, set group_key, TKIP\n", __func__);
4947 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
4948 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
4949 param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
4950 /* set mic key */
4951 memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
4952 memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
4953
4954 psecuritypriv->busetkipkey = true;
4955 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
4956 DBG_88E("%s, set group_key, CCMP\n", __func__);
4957 psecuritypriv->dot118021XGrpPrivacy = _AES_;
4958 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
4959 param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
4960 } else {
4961 DBG_88E("%s, set group_key, none\n", __func__);
4962 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
4963 }
4964 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
4965 psecuritypriv->binstallGrpkey = true;
4966 psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* */
4967 set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
4968 pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
4969 if (pbcmc_sta) {
4970 pbcmc_sta->ieee8021x_blocked = false;
4971 pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
4972 }
4973 }
4974 goto exit;
4975 }
4976
4977 if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x */
4978 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
4979 if (param->u.crypt.set_tx == 1) {
4980 memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
4981
4982 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
4983 DBG_88E("%s, set pairwise key, WEP\n", __func__);
4984
4985 psta->dot118021XPrivacy = _WEP40_;
4986 if (param->u.crypt.key_len == 13)
4987 psta->dot118021XPrivacy = _WEP104_;
4988 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
4989 DBG_88E("%s, set pairwise key, TKIP\n", __func__);
4990
4991 psta->dot118021XPrivacy = _TKIP_;
4992
4993 /* set mic key */
4994 memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
4995 memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
4996
4997 psecuritypriv->busetkipkey = true;
4998 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
4999 DBG_88E("%s, set pairwise key, CCMP\n", __func__);
5000
5001 psta->dot118021XPrivacy = _AES_;
5002 } else {
5003 DBG_88E("%s, set pairwise key, none\n", __func__);
5004
5005 psta->dot118021XPrivacy = _NO_PRIVACY_;
5006 }
5007
5008 set_pairwise_key(padapter, psta);
5009
5010 psta->ieee8021x_blocked = false;
5011 } else { /* group key??? */
5012 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
5013 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
5014 param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
5015 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
5016 if (param->u.crypt.key_len == 13)
5017 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
5018 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
5019 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
5020
5021 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
5022 param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
5023
5024 /* set mic key */
5025 memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
5026 memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
5027
5028 psecuritypriv->busetkipkey = true;
5029 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
5030 psecuritypriv->dot118021XGrpPrivacy = _AES_;
5031
5032 memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
5033 param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
5034 } else {
5035 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
5036 }
5037
5038 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
5039
5040 psecuritypriv->binstallGrpkey = true;
5041
5042 psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* */
5043
5044 set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
5045
5046 pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
5047 if (pbcmc_sta) {
5048 pbcmc_sta->ieee8021x_blocked = false;
5049 pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
5050 }
5051 }
5052 }
5053 }
5054
5055 exit:
5056
5057 kfree(pwep);
5058
5059 return ret;
5060 }
5061
5062 static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
5063 {
5064 int ret = 0;
5065 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5066 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5067 struct sta_priv *pstapriv = &padapter->stapriv;
5068 unsigned char *pbuf = param->u.bcn_ie.buf;
5069
5070 DBG_88E("%s, len =%d\n", __func__, len);
5071
5072 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5073 return -EINVAL;
5074
5075 memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
5076
5077 if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
5078 pstapriv->max_num_sta = NUM_STA;
5079
5080 if (rtw_check_beacon_data(padapter, pbuf, (len-12-2)) == _SUCCESS)/* 12 = param header, 2:no packed */
5081 ret = 0;
5082 else
5083 ret = -EINVAL;
5084
5085 return ret;
5086 }
5087
5088 static int rtw_hostapd_sta_flush(struct net_device *dev)
5089 {
5090 int ret = 0;
5091 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5092
5093 DBG_88E("%s\n", __func__);
5094
5095 flush_all_cam_entry(padapter); /* clear CAM */
5096
5097 ret = rtw_sta_flush(padapter);
5098
5099 return ret;
5100 }
5101
5102 static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
5103 {
5104 int ret = 0;
5105 struct sta_info *psta = NULL;
5106 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5107 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5108 struct sta_priv *pstapriv = &padapter->stapriv;
5109
5110 DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr));
5111
5112 if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)))
5113 return -EINVAL;
5114
5115 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
5116 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
5117 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
5118 return -EINVAL;
5119
5120 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
5121 if (psta) {
5122 int flags = param->u.add_sta.flags;
5123
5124 psta->aid = param->u.add_sta.aid;/* aid = 1~2007 */
5125
5126 memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
5127
5128 /* check wmm cap. */
5129 if (WLAN_STA_WME&flags)
5130 psta->qos_option = 1;
5131 else
5132 psta->qos_option = 0;
5133
5134 if (pmlmepriv->qospriv.qos_option == 0)
5135 psta->qos_option = 0;
5136
5137 /* chec 802.11n ht cap. */
5138 if (WLAN_STA_HT&flags) {
5139 psta->htpriv.ht_option = true;
5140 psta->qos_option = 1;
5141 memcpy((void *)&psta->htpriv.ht_cap, (void *)&param->u.add_sta.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
5142 } else {
5143 psta->htpriv.ht_option = false;
5144 }
5145
5146 if (pmlmepriv->htpriv.ht_option == false)
5147 psta->htpriv.ht_option = false;
5148
5149 update_sta_info_apmode(padapter, psta);
5150 } else {
5151 ret = -ENOMEM;
5152 }
5153
5154 return ret;
5155 }
5156
5157 static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
5158 {
5159 int ret = 0;
5160 struct sta_info *psta = NULL;
5161 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5162 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5163 struct sta_priv *pstapriv = &padapter->stapriv;
5164 int updated = 0;
5165
5166 DBG_88E("rtw_del_sta =%pM\n", (param->sta_addr));
5167
5168 if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
5169 return -EINVAL;
5170
5171 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
5172 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
5173 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
5174 return -EINVAL;
5175
5176 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
5177 if (psta) {
5178 spin_lock_bh(&pstapriv->asoc_list_lock);
5179 if (!list_empty(&psta->asoc_list)) {
5180 rtw_list_delete(&psta->asoc_list);
5181 pstapriv->asoc_list_cnt--;
5182 updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
5183 }
5184 spin_unlock_bh(&pstapriv->asoc_list_lock);
5185 associated_clients_update(padapter, updated);
5186 psta = NULL;
5187 } else {
5188 DBG_88E("rtw_del_sta(), sta has already been removed or never been added\n");
5189 }
5190
5191 return ret;
5192 }
5193
5194 static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
5195 {
5196 int ret = 0;
5197 struct sta_info *psta = NULL;
5198 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5199 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5200 struct sta_priv *pstapriv = &padapter->stapriv;
5201 struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
5202 struct sta_data *psta_data = (struct sta_data *)param_ex->data;
5203
5204 DBG_88E("rtw_ioctl_get_sta_info, sta_addr: %pM\n", (param_ex->sta_addr));
5205
5206 if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
5207 return -EINVAL;
5208
5209 if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
5210 param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
5211 param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff)
5212 return -EINVAL;
5213
5214 psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
5215 if (psta) {
5216 psta_data->aid = (u16)psta->aid;
5217 psta_data->capability = psta->capability;
5218 psta_data->flags = psta->flags;
5219
5220 /*
5221 nonerp_set : BIT(0)
5222 no_short_slot_time_set : BIT(1)
5223 no_short_preamble_set : BIT(2)
5224 no_ht_gf_set : BIT(3)
5225 no_ht_set : BIT(4)
5226 ht_20mhz_set : BIT(5)
5227 */
5228
5229 psta_data->sta_set = ((psta->nonerp_set) |
5230 (psta->no_short_slot_time_set << 1) |
5231 (psta->no_short_preamble_set << 2) |
5232 (psta->no_ht_gf_set << 3) |
5233 (psta->no_ht_set << 4) |
5234 (psta->ht_20mhz_set << 5));
5235 psta_data->tx_supp_rates_len = psta->bssratelen;
5236 memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
5237 memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
5238 psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
5239 psta_data->rx_bytes = psta->sta_stats.rx_bytes;
5240 psta_data->rx_drops = psta->sta_stats.rx_drops;
5241 psta_data->tx_pkts = psta->sta_stats.tx_pkts;
5242 psta_data->tx_bytes = psta->sta_stats.tx_bytes;
5243 psta_data->tx_drops = psta->sta_stats.tx_drops;
5244 } else {
5245 ret = -1;
5246 }
5247
5248 return ret;
5249 }
5250
5251 static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
5252 {
5253 int ret = 0;
5254 struct sta_info *psta = NULL;
5255 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5256 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5257 struct sta_priv *pstapriv = &padapter->stapriv;
5258
5259 DBG_88E("rtw_get_sta_wpaie, sta_addr: %pM\n", (param->sta_addr));
5260
5261 if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
5262 return -EINVAL;
5263
5264 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
5265 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
5266 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
5267 return -EINVAL;
5268
5269 psta = rtw_get_stainfo(pstapriv, param->sta_addr);
5270 if (psta) {
5271 if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_GENERIC)) {
5272 int wpa_ie_len;
5273 int copy_len;
5274
5275 wpa_ie_len = psta->wpa_ie[1];
5276 copy_len = ((wpa_ie_len+2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)) : (wpa_ie_len+2);
5277 param->u.wpa_ie.len = copy_len;
5278 memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
5279 } else {
5280 DBG_88E("sta's wpa_ie is NONE\n");
5281 }
5282 } else {
5283 ret = -1;
5284 }
5285
5286 return ret;
5287 }
5288
5289 static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
5290 {
5291 int ret = 0;
5292 unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
5293 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5294 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5295 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
5296 int ie_len;
5297
5298 DBG_88E("%s, len =%d\n", __func__, len);
5299
5300 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5301 return -EINVAL;
5302
5303 ie_len = len-12-2;/* 12 = param header, 2:no packed */
5304
5305 if (pmlmepriv->wps_beacon_ie) {
5306 kfree(pmlmepriv->wps_beacon_ie);
5307 pmlmepriv->wps_beacon_ie = NULL;
5308 }
5309
5310 if (ie_len > 0) {
5311 pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
5312 pmlmepriv->wps_beacon_ie_len = ie_len;
5313 if (pmlmepriv->wps_beacon_ie == NULL) {
5314 DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
5315 return -EINVAL;
5316 }
5317
5318 memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
5319
5320 update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
5321
5322 pmlmeext->bstart_bss = true;
5323 }
5324
5325 return ret;
5326 }
5327
5328 static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
5329 {
5330 int ret = 0;
5331 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5332 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5333 int ie_len;
5334
5335 DBG_88E("%s, len =%d\n", __func__, len);
5336
5337 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5338 return -EINVAL;
5339
5340 ie_len = len-12-2;/* 12 = param header, 2:no packed */
5341
5342 if (pmlmepriv->wps_probe_resp_ie) {
5343 kfree(pmlmepriv->wps_probe_resp_ie);
5344 pmlmepriv->wps_probe_resp_ie = NULL;
5345 }
5346
5347 if (ie_len > 0) {
5348 pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
5349 pmlmepriv->wps_probe_resp_ie_len = ie_len;
5350 if (pmlmepriv->wps_probe_resp_ie == NULL) {
5351 DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
5352 return -EINVAL;
5353 }
5354 memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
5355 }
5356
5357 return ret;
5358 }
5359
5360 static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
5361 {
5362 int ret = 0;
5363 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5364 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5365 int ie_len;
5366
5367 DBG_88E("%s, len =%d\n", __func__, len);
5368
5369 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5370 return -EINVAL;
5371
5372 ie_len = len-12-2;/* 12 = param header, 2:no packed */
5373
5374 if (pmlmepriv->wps_assoc_resp_ie) {
5375 kfree(pmlmepriv->wps_assoc_resp_ie);
5376 pmlmepriv->wps_assoc_resp_ie = NULL;
5377 }
5378
5379 if (ie_len > 0) {
5380 pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
5381 pmlmepriv->wps_assoc_resp_ie_len = ie_len;
5382 if (pmlmepriv->wps_assoc_resp_ie == NULL) {
5383 DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
5384 return -EINVAL;
5385 }
5386
5387 memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
5388 }
5389
5390 return ret;
5391 }
5392
5393 static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
5394 {
5395 int ret = 0;
5396 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5397 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5398 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
5399 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5400
5401 u8 value;
5402
5403 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5404 return -EINVAL;
5405
5406 if (param->u.wpa_param.name != 0) /* dummy test... */
5407 DBG_88E("%s name(%u) != 0\n", __func__, param->u.wpa_param.name);
5408 value = param->u.wpa_param.value;
5409
5410 /* use the same definition of hostapd's ignore_broadcast_ssid */
5411 if (value != 1 && value != 2)
5412 value = 0;
5413 DBG_88E("%s value(%u)\n", __func__, value);
5414 pmlmeinfo->hidden_ssid_mode = value;
5415 return ret;
5416 }
5417
5418 static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
5419 {
5420 int ret = 0;
5421 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5422 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5423
5424 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5425 return -EINVAL;
5426
5427 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
5428 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
5429 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
5430 return -EINVAL;
5431 ret = rtw_acl_remove_sta(padapter, param->sta_addr);
5432 return ret;
5433 }
5434
5435 static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
5436 {
5437 int ret = 0;
5438 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5439 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5440
5441 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5442 return -EINVAL;
5443
5444 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
5445 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
5446 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
5447 return -EINVAL;
5448 ret = rtw_acl_add_sta(padapter, param->sta_addr);
5449 return ret;
5450 }
5451
5452 static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
5453 {
5454 int ret = 0;
5455 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5456 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5457
5458 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5459 return -EINVAL;
5460
5461 rtw_set_macaddr_acl(padapter, param->u.mlme.command);
5462
5463 return ret;
5464 }
5465
5466 static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
5467 {
5468 struct ieee_param *param;
5469 int ret = 0;
5470 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5471
5472 /*
5473 * this function is expect to call in master mode, which allows no power saving
5474 * so, we just check hw_init_completed
5475 */
5476
5477 if (!padapter->hw_init_completed) {
5478 ret = -EPERM;
5479 goto out;
5480 }
5481
5482 if (!p->pointer) {
5483 ret = -EINVAL;
5484 goto out;
5485 }
5486
5487 param = (struct ieee_param *)rtw_malloc(p->length);
5488 if (param == NULL) {
5489 ret = -ENOMEM;
5490 goto out;
5491 }
5492
5493 if (copy_from_user(param, p->pointer, p->length)) {
5494 kfree(param);
5495 ret = -EFAULT;
5496 goto out;
5497 }
5498
5499 switch (param->cmd) {
5500 case RTL871X_HOSTAPD_FLUSH:
5501 ret = rtw_hostapd_sta_flush(dev);
5502 break;
5503 case RTL871X_HOSTAPD_ADD_STA:
5504 ret = rtw_add_sta(dev, param);
5505 break;
5506 case RTL871X_HOSTAPD_REMOVE_STA:
5507 ret = rtw_del_sta(dev, param);
5508 break;
5509 case RTL871X_HOSTAPD_SET_BEACON:
5510 ret = rtw_set_beacon(dev, param, p->length);
5511 break;
5512 case RTL871X_SET_ENCRYPTION:
5513 ret = rtw_set_encryption(dev, param, p->length);
5514 break;
5515 case RTL871X_HOSTAPD_GET_WPAIE_STA:
5516 ret = rtw_get_sta_wpaie(dev, param);
5517 break;
5518 case RTL871X_HOSTAPD_SET_WPS_BEACON:
5519 ret = rtw_set_wps_beacon(dev, param, p->length);
5520 break;
5521 case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
5522 ret = rtw_set_wps_probe_resp(dev, param, p->length);
5523 break;
5524 case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
5525 ret = rtw_set_wps_assoc_resp(dev, param, p->length);
5526 break;
5527 case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
5528 ret = rtw_set_hidden_ssid(dev, param, p->length);
5529 break;
5530 case RTL871X_HOSTAPD_GET_INFO_STA:
5531 ret = rtw_ioctl_get_sta_data(dev, param, p->length);
5532 break;
5533 case RTL871X_HOSTAPD_SET_MACADDR_ACL:
5534 ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
5535 break;
5536 case RTL871X_HOSTAPD_ACL_ADD_STA:
5537 ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
5538 break;
5539 case RTL871X_HOSTAPD_ACL_REMOVE_STA:
5540 ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
5541 break;
5542 default:
5543 DBG_88E("Unknown hostapd request: %d\n", param->cmd);
5544 ret = -EOPNOTSUPP;
5545 break;
5546 }
5547
5548 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
5549 ret = -EFAULT;
5550 kfree(param);
5551 out:
5552 return ret;
5553 }
5554 #endif
5555
5556 #include <rtw_android.h>
5557 static int rtw_wx_set_priv(struct net_device *dev,
5558 struct iw_request_info *info,
5559 union iwreq_data *awrq,
5560 char *extra)
5561 {
5562 int ret = 0;
5563 int len = 0;
5564 char *ext;
5565 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5566 struct iw_point *dwrq = (struct iw_point *)awrq;
5567
5568 if (dwrq->length == 0)
5569 return -EFAULT;
5570
5571 len = dwrq->length;
5572 ext = vmalloc(len);
5573 if (!ext)
5574 return -ENOMEM;
5575
5576 if (copy_from_user(ext, dwrq->pointer, len)) {
5577 vfree(ext);
5578 return -EFAULT;
5579 }
5580
5581 /* added for wps2.0 @20110524 */
5582 if (dwrq->flags == 0x8766 && len > 8) {
5583 u32 cp_sz;
5584 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5585 u8 *probereq_wpsie = ext;
5586 int probereq_wpsie_len = len;
5587 u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
5588
5589 if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
5590 (!memcmp(&probereq_wpsie[2], wps_oui, 4))) {
5591 cp_sz = probereq_wpsie_len > MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN : probereq_wpsie_len;
5592
5593 pmlmepriv->wps_probe_req_ie_len = 0;
5594 kfree(pmlmepriv->wps_probe_req_ie);
5595 pmlmepriv->wps_probe_req_ie = NULL;
5596
5597 pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
5598 if (pmlmepriv->wps_probe_req_ie == NULL) {
5599 pr_info("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
5600 ret = -EINVAL;
5601 goto FREE_EXT;
5602 }
5603 memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
5604 pmlmepriv->wps_probe_req_ie_len = cp_sz;
5605 }
5606 goto FREE_EXT;
5607 }
5608
5609 if (len >= WEXT_CSCAN_HEADER_SIZE &&
5610 !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
5611 ret = rtw_wx_set_scan(dev, info, awrq, ext);
5612 goto FREE_EXT;
5613 }
5614
5615 FREE_EXT:
5616
5617 vfree(ext);
5618
5619 return ret;
5620 }
5621
5622 static int rtw_pm_set(struct net_device *dev,
5623 struct iw_request_info *info,
5624 union iwreq_data *wrqu, char *extra)
5625 {
5626 int ret = 0;
5627 unsigned mode = 0;
5628 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
5629
5630 DBG_88E("[%s] extra = %s\n", __func__, extra);
5631
5632 if (!memcmp(extra, "lps =", 4)) {
5633 ret = sscanf(extra+4, "%u", &mode);
5634 if (ret != 1)
5635 return -EINVAL;
5636 ret = rtw_pm_set_lps(padapter, mode);
5637 } else if (!memcmp(extra, "ips =", 4)) {
5638 ret = sscanf(extra+4, "%u", &mode);
5639 if (ret != 1)
5640 return -EINVAL;
5641 ret = rtw_pm_set_ips(padapter, mode);
5642 } else {
5643 ret = -EINVAL;
5644 }
5645
5646 return ret;
5647 }
5648
5649 static int rtw_mp_efuse_get(struct net_device *dev,
5650 struct iw_request_info *info,
5651 union iwreq_data *wdata, char *extra)
5652 {
5653 struct adapter *padapter = rtw_netdev_priv(dev);
5654 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
5655 struct hal_data_8188e *haldata = GET_HAL_DATA(padapter);
5656 struct efuse_hal *pEfuseHal;
5657 struct iw_point *wrqu;
5658
5659 u8 *PROMContent = pEEPROM->efuse_eeprom_data;
5660 u8 ips_mode = 0, lps_mode = 0;
5661 struct pwrctrl_priv *pwrctrlpriv;
5662 u8 *data = NULL;
5663 u8 *rawdata = NULL;
5664 char *pch, *ptmp, *token, *tmp[3] = {NULL, NULL, NULL};
5665 u16 i = 0, j = 0, mapLen = 0, addr = 0, cnts = 0;
5666 u16 max_available_size = 0, raw_cursize = 0, raw_maxsize = 0;
5667 int err;
5668 u8 org_fw_iol = padapter->registrypriv.fw_iol;/* 0:Disable, 1:enable, 2:by usb speed */
5669
5670 wrqu = (struct iw_point *)wdata;
5671 pwrctrlpriv = &padapter->pwrctrlpriv;
5672 pEfuseHal = &haldata->EfuseHal;
5673
5674 err = 0;
5675 data = _rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN);
5676 if (data == NULL) {
5677 err = -ENOMEM;
5678 goto exit;
5679 }
5680 rawdata = _rtw_zmalloc(EFUSE_BT_MAX_MAP_LEN);
5681 if (rawdata == NULL) {
5682 err = -ENOMEM;
5683 goto exit;
5684 }
5685
5686 if (copy_from_user(extra, wrqu->pointer, wrqu->length)) {
5687 err = -EFAULT;
5688 goto exit;
5689 }
5690 lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */
5691 rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
5692
5693 ips_mode = pwrctrlpriv->ips_mode;/* keep org value */
5694 rtw_pm_set_ips(padapter, IPS_NONE);
5695
5696 pch = extra;
5697 DBG_88E("%s: in =%s\n", __func__, extra);
5698
5699 i = 0;
5700 /* mac 16 "00e04c871200" rmap, 00, 2 */
5701 while ((token = strsep(&pch, ",")) != NULL) {
5702 if (i > 2)
5703 break;
5704 tmp[i] = token;
5705 i++;
5706 }
5707 padapter->registrypriv.fw_iol = 0;/* 0:Disable, 1:enable, 2:by usb speed */
5708
5709 if (strcmp(tmp[0], "status") == 0) {
5710 sprintf(extra, "Load File efuse =%s, Load File MAC =%s", (pEEPROM->bloadfile_fail_flag ? "FAIL" : "OK"), (pEEPROM->bloadmac_fail_flag ? "FAIL" : "OK"));
5711
5712 goto exit;
5713 } else if (strcmp(tmp[0], "filemap") == 0) {
5714 mapLen = EFUSE_MAP_SIZE;
5715
5716 sprintf(extra, "\n");
5717 for (i = 0; i < EFUSE_MAP_SIZE; i += 16) {
5718 sprintf(extra, "%s0x%02x\t", extra, i);
5719 for (j = 0; j < 8; j++)
5720 sprintf(extra, "%s%02X ", extra, PROMContent[i+j]);
5721 sprintf(extra, "%s\t", extra);
5722 for (; j < 16; j++)
5723 sprintf(extra, "%s%02X ", extra, PROMContent[i+j]);
5724 sprintf(extra, "%s\n", extra);
5725 }
5726 } else if (strcmp(tmp[0], "realmap") == 0) {
5727 mapLen = EFUSE_MAP_SIZE;
5728 if (rtw_efuse_map_read(padapter, 0, mapLen, pEfuseHal->fakeEfuseInitMap) == _FAIL) {
5729 DBG_88E("%s: read realmap Fail!!\n", __func__);
5730 err = -EFAULT;
5731 goto exit;
5732 }
5733
5734 sprintf(extra, "\n");
5735 for (i = 0; i < EFUSE_MAP_SIZE; i += 16) {
5736 sprintf(extra, "%s0x%02x\t", extra, i);
5737 for (j = 0; j < 8; j++)
5738 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseInitMap[i+j]);
5739 sprintf(extra, "%s\t", extra);
5740 for (; j < 16; j++)
5741 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseInitMap[i+j]);
5742 sprintf(extra, "%s\n", extra);
5743 }
5744 } else if (strcmp(tmp[0], "rmap") == 0) {
5745 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
5746 DBG_88E("%s: rmap Fail!! Parameters error!\n", __func__);
5747 err = -EINVAL;
5748 goto exit;
5749 }
5750
5751 /* rmap addr cnts */
5752 addr = simple_strtoul(tmp[1], &ptmp, 16);
5753 DBG_88E("%s: addr =%x\n", __func__, addr);
5754
5755 cnts = simple_strtoul(tmp[2], &ptmp, 10);
5756 if (cnts == 0) {
5757 DBG_88E("%s: rmap Fail!! cnts error!\n", __func__);
5758 err = -EINVAL;
5759 goto exit;
5760 }
5761 DBG_88E("%s: cnts =%d\n", __func__, cnts);
5762
5763 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size);
5764 if ((addr + cnts) > max_available_size) {
5765 DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
5766 err = -EINVAL;
5767 goto exit;
5768 }
5769
5770 if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
5771 DBG_88E("%s: rtw_efuse_map_read error!\n", __func__);
5772 err = -EFAULT;
5773 goto exit;
5774 }
5775
5776 *extra = 0;
5777 for (i = 0; i < cnts; i++)
5778 sprintf(extra, "%s0x%02X ", extra, data[i]);
5779 } else if (strcmp(tmp[0], "realraw") == 0) {
5780 addr = 0;
5781 mapLen = EFUSE_MAX_SIZE;
5782 if (rtw_efuse_access(padapter, false, addr, mapLen, rawdata) == _FAIL) {
5783 DBG_88E("%s: rtw_efuse_access Fail!!\n", __func__);
5784 err = -EFAULT;
5785 goto exit;
5786 }
5787
5788 sprintf(extra, "\n");
5789 for (i = 0; i < mapLen; i++) {
5790 sprintf(extra, "%s%02X", extra, rawdata[i]);
5791
5792 if ((i & 0xF) == 0xF)
5793 sprintf(extra, "%s\n", extra);
5794 else if ((i & 0x7) == 0x7)
5795 sprintf(extra, "%s\t", extra);
5796 else
5797 sprintf(extra, "%s ", extra);
5798 }
5799 } else if (strcmp(tmp[0], "mac") == 0) {
5800 cnts = 6;
5801
5802 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size);
5803 if ((addr + cnts) > max_available_size) {
5804 DBG_88E("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __func__, addr, cnts);
5805 err = -EFAULT;
5806 goto exit;
5807 }
5808
5809 if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
5810 DBG_88E("%s: rtw_efuse_map_read error!\n", __func__);
5811 err = -EFAULT;
5812 goto exit;
5813 }
5814
5815 *extra = 0;
5816 for (i = 0; i < cnts; i++) {
5817 sprintf(extra, "%s%02X", extra, data[i]);
5818 if (i != (cnts-1))
5819 sprintf(extra, "%s:", extra);
5820 }
5821 } else if (strcmp(tmp[0], "vidpid") == 0) {
5822 cnts = 4;
5823
5824 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size);
5825 if ((addr + cnts) > max_available_size) {
5826 DBG_88E("%s: addr(0x%02x)+cnts(%d) parameter error!\n", __func__, addr, cnts);
5827 err = -EFAULT;
5828 goto exit;
5829 }
5830 if (rtw_efuse_map_read(padapter, addr, cnts, data) == _FAIL) {
5831 DBG_88E("%s: rtw_efuse_access error!!\n", __func__);
5832 err = -EFAULT;
5833 goto exit;
5834 }
5835
5836 *extra = 0;
5837 for (i = 0; i < cnts; i++) {
5838 sprintf(extra, "%s0x%02X", extra, data[i]);
5839 if (i != (cnts-1))
5840 sprintf(extra, "%s,", extra);
5841 }
5842 } else if (strcmp(tmp[0], "ableraw") == 0) {
5843 efuse_GetCurrentSize(padapter, &raw_cursize);
5844 raw_maxsize = efuse_GetMaxSize(padapter);
5845 sprintf(extra, "[available raw size] = %d bytes", raw_maxsize-raw_cursize);
5846 } else if (strcmp(tmp[0], "btffake") == 0) {
5847 sprintf(extra, "\n");
5848 for (i = 0; i < 512; i += 16) {
5849 sprintf(extra, "%s0x%03x\t", extra, i);
5850 for (j = 0; j < 8; j++)
5851 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
5852 sprintf(extra, "%s\t", extra);
5853 for (; j < 16; j++)
5854 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
5855 sprintf(extra, "%s\n", extra);
5856 }
5857 } else if (strcmp(tmp[0], "btbfake") == 0) {
5858 sprintf(extra, "\n");
5859 for (i = 512; i < 1024; i += 16) {
5860 sprintf(extra, "%s0x%03x\t", extra, i);
5861 for (j = 0; j < 8; j++)
5862 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
5863 sprintf(extra, "%s\t", extra);
5864 for (; j < 16; j++)
5865 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeBTEfuseModifiedMap[i+j]);
5866 sprintf(extra, "%s\n", extra);
5867 }
5868 } else if (strcmp(tmp[0], "wlrfkmap") == 0) {
5869 sprintf(extra, "\n");
5870 for (i = 0; i < EFUSE_MAP_SIZE; i += 16) {
5871 sprintf(extra, "%s0x%02x\t", extra, i);
5872 for (j = 0; j < 8; j++)
5873 sprintf(extra, "%s%02X ", extra, pEfuseHal->fakeEfuseModifiedMap[i+j]);
5874 sprintf(extra, "%s\t", extra);
5875 for (; j < 16; j++)
5876 sprintf(extra, "%s %02X", extra, pEfuseHal->fakeEfuseModifiedMap[i+j]);
5877 sprintf(extra, "%s\n", extra);
5878 }
5879 } else {
5880 sprintf(extra, "Command not found!");
5881 }
5882
5883 exit:
5884 kfree(data);
5885 kfree(rawdata);
5886 if (!err)
5887 wrqu->length = strlen(extra);
5888
5889 rtw_pm_set_ips(padapter, ips_mode);
5890 rtw_pm_set_lps(padapter, lps_mode);
5891 padapter->registrypriv.fw_iol = org_fw_iol;/* 0:Disable, 1:enable, 2:by usb speed */
5892 return err;
5893 }
5894
5895 static int rtw_mp_efuse_set(struct net_device *dev,
5896 struct iw_request_info *info,
5897 union iwreq_data *wdata, char *extra)
5898 {
5899 struct adapter *padapter;
5900 struct pwrctrl_priv *pwrctrlpriv;
5901 struct hal_data_8188e *haldata;
5902 struct efuse_hal *pEfuseHal;
5903
5904 u8 ips_mode = 0, lps_mode = 0;
5905 u32 i, jj, kk;
5906 u8 *setdata = NULL;
5907 u8 *ShadowMapBT = NULL;
5908 u8 *ShadowMapWiFi = NULL;
5909 u8 *setrawdata = NULL;
5910 char *pch, *ptmp, *token, *tmp[3] = {NULL, NULL, NULL};
5911 u16 addr = 0, cnts = 0, max_available_size = 0;
5912 int err;
5913
5914 padapter = rtw_netdev_priv(dev);
5915 pwrctrlpriv = &padapter->pwrctrlpriv;
5916 haldata = GET_HAL_DATA(padapter);
5917 pEfuseHal = &haldata->EfuseHal;
5918 err = 0;
5919 setdata = _rtw_zmalloc(1024);
5920 if (setdata == NULL) {
5921 err = -ENOMEM;
5922 goto exit;
5923 }
5924 ShadowMapBT = _rtw_malloc(EFUSE_BT_MAX_MAP_LEN);
5925 if (ShadowMapBT == NULL) {
5926 err = -ENOMEM;
5927 goto exit;
5928 }
5929 ShadowMapWiFi = _rtw_malloc(EFUSE_MAP_SIZE);
5930 if (ShadowMapWiFi == NULL) {
5931 err = -ENOMEM;
5932 goto exit;
5933 }
5934 setrawdata = _rtw_malloc(EFUSE_MAX_SIZE);
5935 if (setrawdata == NULL) {
5936 err = -ENOMEM;
5937 goto exit;
5938 }
5939
5940 lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */
5941 rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
5942
5943 ips_mode = pwrctrlpriv->ips_mode;/* keep org value */
5944 rtw_pm_set_ips(padapter, IPS_NONE);
5945
5946 pch = extra;
5947 DBG_88E("%s: in =%s\n", __func__, extra);
5948
5949 i = 0;
5950 while ((token = strsep(&pch, ",")) != NULL) {
5951 if (i > 2)
5952 break;
5953 tmp[i] = token;
5954 i++;
5955 }
5956
5957 /* tmp[0],[1],[2] */
5958 /* wmap, addr, 00e04c871200 */
5959 if (strcmp(tmp[0], "wmap") == 0) {
5960 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
5961 err = -EINVAL;
5962 goto exit;
5963 }
5964
5965 addr = simple_strtoul(tmp[1], &ptmp, 16);
5966 addr &= 0xFFF;
5967
5968 cnts = strlen(tmp[2]);
5969 if (cnts%2) {
5970 err = -EINVAL;
5971 goto exit;
5972 }
5973 cnts /= 2;
5974 if (cnts == 0) {
5975 err = -EINVAL;
5976 goto exit;
5977 }
5978
5979 DBG_88E("%s: addr = 0x%X\n", __func__, addr);
5980 DBG_88E("%s: cnts =%d\n", __func__, cnts);
5981 DBG_88E("%s: map data =%s\n", __func__, tmp[2]);
5982
5983 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
5984 setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
5985 /* Change to check TYPE_EFUSE_MAP_LEN, because 8188E raw 256, logic map over 256. */
5986 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_size);
5987 if ((addr+cnts) > max_available_size) {
5988 DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
5989 err = -EFAULT;
5990 goto exit;
5991 }
5992
5993 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
5994 DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__);
5995 err = -EFAULT;
5996 goto exit;
5997 }
5998 } else if (strcmp(tmp[0], "wraw") == 0) {
5999 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
6000 err = -EINVAL;
6001 goto exit;
6002 }
6003
6004 addr = simple_strtoul(tmp[1], &ptmp, 16);
6005 addr &= 0xFFF;
6006
6007 cnts = strlen(tmp[2]);
6008 if (cnts%2) {
6009 err = -EINVAL;
6010 goto exit;
6011 }
6012 cnts /= 2;
6013 if (cnts == 0) {
6014 err = -EINVAL;
6015 goto exit;
6016 }
6017
6018 DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6019 DBG_88E("%s: cnts =%d\n", __func__, cnts);
6020 DBG_88E("%s: raw data =%s\n", __func__, tmp[2]);
6021
6022 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6023 setrawdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
6024
6025 if (rtw_efuse_access(padapter, true, addr, cnts, setrawdata) == _FAIL) {
6026 DBG_88E("%s: rtw_efuse_access error!!\n", __func__);
6027 err = -EFAULT;
6028 goto exit;
6029 }
6030 } else if (strcmp(tmp[0], "mac") == 0) {
6031 if (tmp[1] == NULL) {
6032 err = -EINVAL;
6033 goto exit;
6034 }
6035
6036 /* mac, 00e04c871200 */
6037 addr = EEPROM_MAC_ADDR_88EU;
6038 cnts = strlen(tmp[1]);
6039 if (cnts%2) {
6040 err = -EINVAL;
6041 goto exit;
6042 }
6043 cnts /= 2;
6044 if (cnts == 0) {
6045 err = -EINVAL;
6046 goto exit;
6047 }
6048 if (cnts > 6) {
6049 DBG_88E("%s: error data for mac addr =\"%s\"\n", __func__, tmp[1]);
6050 err = -EFAULT;
6051 goto exit;
6052 }
6053
6054 DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6055 DBG_88E("%s: cnts =%d\n", __func__, cnts);
6056 DBG_88E("%s: MAC address =%s\n", __func__, tmp[1]);
6057
6058 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6059 setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
6060 /* Change to check TYPE_EFUSE_MAP_LEN, because 8188E raw 256, logic map over 256. */
6061 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_size);
6062 if ((addr+cnts) > max_available_size) {
6063 DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
6064 err = -EFAULT;
6065 goto exit;
6066 }
6067
6068 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
6069 DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__);
6070 err = -EFAULT;
6071 goto exit;
6072 }
6073 } else if (strcmp(tmp[0], "vidpid") == 0) {
6074 if (tmp[1] == NULL) {
6075 err = -EINVAL;
6076 goto exit;
6077 }
6078
6079 /* pidvid, da0b7881 */
6080 addr = EEPROM_VID_88EE;
6081 cnts = strlen(tmp[1]);
6082 if (cnts%2) {
6083 err = -EINVAL;
6084 goto exit;
6085 }
6086 cnts /= 2;
6087 if (cnts == 0) {
6088 err = -EINVAL;
6089 goto exit;
6090 }
6091
6092 DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6093 DBG_88E("%s: cnts =%d\n", __func__, cnts);
6094 DBG_88E("%s: VID/PID =%s\n", __func__, tmp[1]);
6095
6096 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6097 setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
6098
6099 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size);
6100 if ((addr+cnts) > max_available_size) {
6101 DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
6102 err = -EFAULT;
6103 goto exit;
6104 }
6105
6106 if (rtw_efuse_map_write(padapter, addr, cnts, setdata) == _FAIL) {
6107 DBG_88E("%s: rtw_efuse_map_write error!!\n", __func__);
6108 err = -EFAULT;
6109 goto exit;
6110 }
6111 } else if (strcmp(tmp[0], "btwmap") == 0) {
6112 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
6113 err = -EINVAL;
6114 goto exit;
6115 }
6116
6117 addr = simple_strtoul(tmp[1], &ptmp, 16);
6118 addr &= 0xFFF;
6119
6120 cnts = strlen(tmp[2]);
6121 if (cnts%2) {
6122 err = -EINVAL;
6123 goto exit;
6124 }
6125 cnts /= 2;
6126 if (cnts == 0) {
6127 err = -EINVAL;
6128 goto exit;
6129 }
6130
6131 DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6132 DBG_88E("%s: cnts =%d\n", __func__, cnts);
6133 DBG_88E("%s: BT data =%s\n", __func__, tmp[2]);
6134
6135 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6136 setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
6137
6138 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size);
6139 if ((addr+cnts) > max_available_size) {
6140 DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
6141 err = -EFAULT;
6142 goto exit;
6143 }
6144
6145 } else if (strcmp(tmp[0], "btwfake") == 0) {
6146 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
6147 err = -EINVAL;
6148 goto exit;
6149 }
6150
6151 addr = simple_strtoul(tmp[1], &ptmp, 16);
6152 addr &= 0xFFF;
6153
6154 cnts = strlen(tmp[2]);
6155 if (cnts%2) {
6156 err = -EINVAL;
6157 goto exit;
6158 }
6159 cnts /= 2;
6160 if (cnts == 0) {
6161 err = -EINVAL;
6162 goto exit;
6163 }
6164
6165 DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6166 DBG_88E("%s: cnts =%d\n", __func__, cnts);
6167 DBG_88E("%s: BT tmp data =%s\n", __func__, tmp[2]);
6168
6169 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6170 pEfuseHal->fakeBTEfuseModifiedMap[addr+jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
6171 } else if (strcmp(tmp[0], "wldumpfake") == 0) {
6172 if (rtw_efuse_map_read(padapter, 0, EFUSE_BT_MAX_MAP_LEN, pEfuseHal->fakeEfuseModifiedMap) == _SUCCESS) {
6173 DBG_88E("%s: BT read all map success\n", __func__);
6174 } else {
6175 DBG_88E("%s: BT read all map Fail\n", __func__);
6176 err = -EFAULT;
6177 }
6178 } else if (strcmp(tmp[0], "btfk2map") == 0) {
6179 memcpy(pEfuseHal->BTEfuseModifiedMap, pEfuseHal->fakeBTEfuseModifiedMap, EFUSE_BT_MAX_MAP_LEN);
6180
6181 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size);
6182 if (max_available_size < 1) {
6183 err = -EFAULT;
6184 goto exit;
6185 }
6186
6187 } else if (strcmp(tmp[0], "wlfk2map") == 0) {
6188 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size);
6189 if (max_available_size < 1) {
6190 err = -EFAULT;
6191 goto exit;
6192 }
6193
6194 if (rtw_efuse_map_write(padapter, 0x00, EFUSE_MAX_MAP_LEN, pEfuseHal->fakeEfuseModifiedMap) == _FAIL) {
6195 DBG_88E("%s: rtw_efuse_map_write error!\n", __func__);
6196 err = -EFAULT;
6197 goto exit;
6198 }
6199 } else if (strcmp(tmp[0], "wlwfake") == 0) {
6200 if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
6201 err = -EINVAL;
6202 goto exit;
6203 }
6204
6205 addr = simple_strtoul(tmp[1], &ptmp, 16);
6206 addr &= 0xFFF;
6207
6208 cnts = strlen(tmp[2]);
6209 if (cnts%2) {
6210 err = -EINVAL;
6211 goto exit;
6212 }
6213 cnts /= 2;
6214 if (cnts == 0) {
6215 err = -EINVAL;
6216 goto exit;
6217 }
6218
6219 DBG_88E("%s: addr = 0x%X\n", __func__, addr);
6220 DBG_88E("%s: cnts =%d\n", __func__, cnts);
6221 DBG_88E("%s: map tmp data =%s\n", __func__, tmp[2]);
6222
6223 for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
6224 pEfuseHal->fakeEfuseModifiedMap[addr+jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
6225 }
6226
6227 exit:
6228 kfree(setdata);
6229 kfree(ShadowMapBT);
6230 kfree(ShadowMapWiFi);
6231 kfree(setrawdata);
6232
6233 rtw_pm_set_ips(padapter, ips_mode);
6234 rtw_pm_set_lps(padapter, lps_mode);
6235
6236 return err;
6237 }
6238
6239 /*
6240 * Input Format: %s,%d,%d
6241 * %s is width, could be
6242 * "b" for 1 byte
6243 * "w" for WORD (2 bytes)
6244 * "dw" for DWORD (4 bytes)
6245 * 1st %d is address(offset)
6246 * 2st %d is data to write
6247 */
6248 static int rtw_mp_write_reg(struct net_device *dev,
6249 struct iw_request_info *info,
6250 struct iw_point *wrqu, char *extra)
6251 {
6252 char *pch, *pnext, *ptmp;
6253 char *width_str;
6254 char width;
6255 u32 addr, data;
6256 int ret;
6257 struct adapter *padapter = rtw_netdev_priv(dev);
6258
6259 pch = extra;
6260 pnext = strpbrk(pch, ",.-");
6261 if (pnext == NULL)
6262 return -EINVAL;
6263 *pnext = 0;
6264 width_str = pch;
6265
6266 pch = pnext + 1;
6267 pnext = strpbrk(pch, ",.-");
6268 if (pnext == NULL)
6269 return -EINVAL;
6270 *pnext = 0;
6271 addr = simple_strtoul(pch, &ptmp, 16);
6272 if (addr > 0x3FFF)
6273 return -EINVAL;
6274
6275 pch = pnext + 1;
6276 if ((pch - extra) >= wrqu->length)
6277 return -EINVAL;
6278 data = simple_strtoul(pch, &ptmp, 16);
6279
6280 ret = 0;
6281 width = width_str[0];
6282 switch (width) {
6283 case 'b':
6284 /* 1 byte */
6285 if (data > 0xFF) {
6286 ret = -EINVAL;
6287 break;
6288 }
6289 usb_write8(padapter, addr, data);
6290 break;
6291 case 'w':
6292 /* 2 bytes */
6293 if (data > 0xFFFF) {
6294 ret = -EINVAL;
6295 break;
6296 }
6297 usb_write16(padapter, addr, data);
6298 break;
6299 case 'd':
6300 /* 4 bytes */
6301 usb_write32(padapter, addr, data);
6302 break;
6303 default:
6304 ret = -EINVAL;
6305 break;
6306 }
6307
6308 return ret;
6309 }
6310
6311 /*
6312 * Input Format: %s,%d
6313 * %s is width, could be
6314 * "b" for 1 byte
6315 * "w" for WORD (2 bytes)
6316 * "dw" for DWORD (4 bytes)
6317 * %d is address(offset)
6318 *
6319 * Return:
6320 * %d for data readed
6321 */
6322 static int rtw_mp_read_reg(struct net_device *dev,
6323 struct iw_request_info *info,
6324 struct iw_point *wrqu, char *extra)
6325 {
6326 struct adapter *padapter = rtw_netdev_priv(dev);
6327 char *input = kmalloc(wrqu->length, GFP_KERNEL);
6328 char *pch, *pnext, *ptmp;
6329 char *width_str;
6330 char width;
6331 char data[20], tmp[20];
6332 u32 addr;
6333 u32 ret, i = 0, j = 0, strtout = 0;
6334
6335 if (!input)
6336 return -ENOMEM;
6337 if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6338 kfree(input);
6339 return -EFAULT;
6340 }
6341 memset(data, 0, 20);
6342 memset(tmp, 0, 20);
6343 memset(extra, 0, wrqu->length);
6344
6345 pch = input;
6346 pnext = strpbrk(pch, ",.-");
6347 if (pnext == NULL) {
6348 kfree(input);
6349 return -EINVAL;
6350 }
6351 *pnext = 0;
6352 width_str = pch;
6353
6354 pch = pnext + 1;
6355 if ((pch - input) >= wrqu->length) {
6356 kfree(input);
6357 return -EINVAL;
6358 }
6359 kfree(input);
6360 addr = simple_strtoul(pch, &ptmp, 16);
6361 if (addr > 0x3FFF)
6362 return -EINVAL;
6363
6364 ret = 0;
6365 width = width_str[0];
6366 switch (width) {
6367 case 'b':
6368 /* 1 byte */
6369 sprintf(extra, "%d\n", usb_read8(padapter, addr));
6370 wrqu->length = strlen(extra);
6371 break;
6372 case 'w':
6373 /* 2 bytes */
6374 sprintf(data, "%04x\n", usb_read16(padapter, addr));
6375 for (i = 0; i <= strlen(data); i++) {
6376 if (i%2 == 0) {
6377 tmp[j] = ' ';
6378 j++;
6379 }
6380 if (data[i] != '\0')
6381 tmp[j] = data[i];
6382 j++;
6383 }
6384 pch = tmp;
6385 DBG_88E("pch =%s", pch);
6386
6387 while (*pch != '\0') {
6388 pnext = strpbrk(pch, " ");
6389 if (!pnext)
6390 break;
6391
6392 pnext++;
6393 if (*pnext != '\0') {
6394 strtout = simple_strtoul(pnext, &ptmp, 16);
6395 sprintf(extra, "%s %d", extra, strtout);
6396 } else {
6397 break;
6398 }
6399 pch = pnext;
6400 }
6401 wrqu->length = 6;
6402 break;
6403 case 'd':
6404 /* 4 bytes */
6405 sprintf(data, "%08x", usb_read32(padapter, addr));
6406 /* add read data format blank */
6407 for (i = 0; i <= strlen(data); i++) {
6408 if (i%2 == 0) {
6409 tmp[j] = ' ';
6410 j++;
6411 }
6412 if (data[i] != '\0')
6413 tmp[j] = data[i];
6414
6415 j++;
6416 }
6417 pch = tmp;
6418 DBG_88E("pch =%s", pch);
6419
6420 while (*pch != '\0') {
6421 pnext = strpbrk(pch, " ");
6422 if (!pnext)
6423 break;
6424 pnext++;
6425 if (*pnext != '\0') {
6426 strtout = simple_strtoul(pnext, &ptmp, 16);
6427 sprintf(extra, "%s %d", extra, strtout);
6428 } else {
6429 break;
6430 }
6431 pch = pnext;
6432 }
6433 wrqu->length = strlen(extra);
6434 break;
6435 default:
6436 wrqu->length = 0;
6437 ret = -EINVAL;
6438 break;
6439 }
6440
6441 return ret;
6442 }
6443
6444 /*
6445 * Input Format: %d,%x,%x
6446 * %d is RF path, should be smaller than MAX_RF_PATH_NUMS
6447 * 1st %x is address(offset)
6448 * 2st %x is data to write
6449 */
6450 static int rtw_mp_write_rf(struct net_device *dev,
6451 struct iw_request_info *info,
6452 struct iw_point *wrqu, char *extra)
6453 {
6454 u32 path, addr, data;
6455 int ret;
6456 struct adapter *padapter = rtw_netdev_priv(dev);
6457
6458 ret = sscanf(extra, "%d,%x,%x", &path, &addr, &data);
6459 if (ret < 3)
6460 return -EINVAL;
6461
6462 if (path >= MAX_RF_PATH_NUMS)
6463 return -EINVAL;
6464 if (addr > 0xFF)
6465 return -EINVAL;
6466 if (data > 0xFFFFF)
6467 return -EINVAL;
6468
6469 memset(extra, 0, wrqu->length);
6470
6471 write_rfreg(padapter, path, addr, data);
6472
6473 sprintf(extra, "write_rf completed\n");
6474 wrqu->length = strlen(extra);
6475
6476 return 0;
6477 }
6478
6479 /*
6480 * Input Format: %d,%x
6481 * %d is RF path, should be smaller than MAX_RF_PATH_NUMS
6482 * %x is address(offset)
6483 *
6484 * Return:
6485 * %d for data readed
6486 */
6487 static int rtw_mp_read_rf(struct net_device *dev,
6488 struct iw_request_info *info,
6489 struct iw_point *wrqu, char *extra)
6490 {
6491 char *input = kmalloc(wrqu->length, GFP_KERNEL);
6492 char *pch, *pnext, *ptmp;
6493 char data[20], tmp[20];
6494 u32 path, addr;
6495 u32 ret, i = 0, j = 0, strtou = 0;
6496 struct adapter *padapter = rtw_netdev_priv(dev);
6497
6498 if (!input)
6499 return -ENOMEM;
6500 if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6501 kfree(input);
6502 return -EFAULT;
6503 }
6504 ret = sscanf(input, "%d,%x", &path, &addr);
6505 kfree(input);
6506 if (ret < 2)
6507 return -EINVAL;
6508
6509 if (path >= MAX_RF_PATH_NUMS)
6510 return -EINVAL;
6511 if (addr > 0xFF)
6512 return -EINVAL;
6513
6514 memset(extra, 0, wrqu->length);
6515
6516 sprintf(data, "%08x", read_rfreg(padapter, path, addr));
6517 /* add read data format blank */
6518 for (i = 0; i <= strlen(data); i++) {
6519 if (i%2 == 0) {
6520 tmp[j] = ' ';
6521 j++;
6522 }
6523 tmp[j] = data[i];
6524 j++;
6525 }
6526 pch = tmp;
6527 DBG_88E("pch =%s", pch);
6528
6529 while (*pch != '\0') {
6530 pnext = strpbrk(pch, " ");
6531 pnext++;
6532 if (*pnext != '\0') {
6533 strtou = simple_strtoul(pnext, &ptmp, 16);
6534 sprintf(extra, "%s %d", extra, strtou);
6535 } else {
6536 break;
6537 }
6538 pch = pnext;
6539 }
6540 wrqu->length = strlen(extra);
6541 return 0;
6542 }
6543
6544 static int rtw_mp_start(struct net_device *dev,
6545 struct iw_request_info *info,
6546 struct iw_point *wrqu, char *extra)
6547 {
6548 struct adapter *padapter = rtw_netdev_priv(dev);
6549
6550 if (padapter->registrypriv.mp_mode == 0) {
6551 padapter->registrypriv.mp_mode = 1;
6552
6553 rtw_pm_set_ips(padapter, IPS_NONE);
6554 LeaveAllPowerSaveMode(padapter);
6555
6556 MPT_InitializeAdapter(padapter, 1);
6557 }
6558 if (padapter->registrypriv.mp_mode == 0)
6559 return -EPERM;
6560 if (padapter->mppriv.mode == MP_OFF) {
6561 if (mp_start_test(padapter) == _FAIL)
6562 return -EPERM;
6563 padapter->mppriv.mode = MP_ON;
6564 }
6565 return 0;
6566 }
6567
6568 static int rtw_mp_stop(struct net_device *dev,
6569 struct iw_request_info *info,
6570 struct iw_point *wrqu, char *extra)
6571 {
6572 struct adapter *padapter = rtw_netdev_priv(dev);
6573
6574 if (padapter->registrypriv.mp_mode == 1) {
6575 MPT_DeInitAdapter(padapter);
6576 padapter->registrypriv.mp_mode = 0;
6577 }
6578
6579 if (padapter->mppriv.mode != MP_OFF) {
6580 mp_stop_test(padapter);
6581 padapter->mppriv.mode = MP_OFF;
6582 }
6583
6584 return 0;
6585 }
6586
6587 extern int wifirate2_ratetbl_inx(unsigned char rate);
6588
6589 static int rtw_mp_rate(struct net_device *dev,
6590 struct iw_request_info *info,
6591 struct iw_point *wrqu, char *extra)
6592 {
6593 u32 rate = MPT_RATE_1M;
6594 char *input = kmalloc(wrqu->length, GFP_KERNEL);
6595 struct adapter *padapter = rtw_netdev_priv(dev);
6596
6597 if (!input)
6598 return -ENOMEM;
6599 if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6600 kfree(input);
6601 return -EFAULT;
6602 }
6603 rate = rtw_atoi(input);
6604 sprintf(extra, "Set data rate to %d", rate);
6605 kfree(input);
6606 if (rate <= 0x7f)
6607 rate = wifirate2_ratetbl_inx((u8)rate);
6608 else
6609 rate = (rate-0x80+MPT_RATE_MCS0);
6610
6611 if (rate >= MPT_RATE_LAST)
6612 return -EINVAL;
6613
6614 padapter->mppriv.rateidx = rate;
6615 Hal_SetDataRate(padapter);
6616
6617 wrqu->length = strlen(extra) + 1;
6618 return 0;
6619 }
6620
6621 static int rtw_mp_channel(struct net_device *dev,
6622 struct iw_request_info *info,
6623 struct iw_point *wrqu, char *extra)
6624 {
6625 struct adapter *padapter = rtw_netdev_priv(dev);
6626 char *input = kmalloc(wrqu->length, GFP_KERNEL);
6627 u32 channel = 1;
6628
6629 if (!input)
6630 return -ENOMEM;
6631 if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6632 kfree(input);
6633 return -EFAULT;
6634 }
6635 channel = rtw_atoi(input);
6636 sprintf(extra, "Change channel %d to channel %d", padapter->mppriv.channel, channel);
6637
6638 padapter->mppriv.channel = channel;
6639 Hal_SetChannel(padapter);
6640
6641 wrqu->length = strlen(extra) + 1;
6642 kfree(input);
6643 return 0;
6644 }
6645
6646 static int rtw_mp_bandwidth(struct net_device *dev,
6647 struct iw_request_info *info,
6648 struct iw_point *wrqu, char *extra)
6649 {
6650 u32 bandwidth = 0, sg = 0;
6651 struct adapter *padapter = rtw_netdev_priv(dev);
6652 int rv;
6653
6654 rv = sscanf(extra, "40M =%d, shortGI =%d", &bandwidth, &sg);
6655 if (rv != 2)
6656 return -EINVAL;
6657
6658 if (bandwidth != HT_CHANNEL_WIDTH_40)
6659 bandwidth = HT_CHANNEL_WIDTH_20;
6660
6661 padapter->mppriv.bandwidth = (u8)bandwidth;
6662 padapter->mppriv.preamble = sg;
6663
6664 SetBandwidth(padapter);
6665
6666 return 0;
6667 }
6668
6669 static int rtw_mp_txpower(struct net_device *dev,
6670 struct iw_request_info *info,
6671 struct iw_point *wrqu, char *extra)
6672 {
6673 u32 idx_a = 0, idx_b = 0;
6674 char *input = kmalloc(wrqu->length, GFP_KERNEL);
6675 struct adapter *padapter = rtw_netdev_priv(dev);
6676 int rv;
6677
6678 if (!input)
6679 return -ENOMEM;
6680 if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6681 kfree(input);
6682 return -EFAULT;
6683 }
6684 rv = sscanf(input, "patha =%d, pathb =%d", &idx_a, &idx_b);
6685 if (rv != 2) {
6686 kfree(input);
6687 return -EINVAL;
6688 }
6689
6690 sprintf(extra, "Set power level path_A:%d path_B:%d", idx_a, idx_b);
6691 padapter->mppriv.txpoweridx = (u8)idx_a;
6692 padapter->mppriv.txpoweridx_b = (u8)idx_b;
6693 padapter->mppriv.bSetTxPower = 1;
6694 Hal_SetAntennaPathPower(padapter);
6695
6696 wrqu->length = strlen(extra) + 1;
6697 kfree(input);
6698 return 0;
6699 }
6700
6701 static int rtw_mp_ant_tx(struct net_device *dev,
6702 struct iw_request_info *info,
6703 struct iw_point *wrqu, char *extra)
6704 {
6705 u8 i;
6706 char *input = kmalloc(wrqu->length, GFP_KERNEL);
6707 u16 antenna = 0;
6708 struct adapter *padapter = rtw_netdev_priv(dev);
6709
6710 if (!input)
6711 return -ENOMEM;
6712 if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6713 kfree(input);
6714 return -EFAULT;
6715 }
6716
6717 sprintf(extra, "switch Tx antenna to %s", input);
6718
6719 for (i = 0; i < strlen(input); i++) {
6720 switch (input[i]) {
6721 case 'a':
6722 antenna |= ANTENNA_A;
6723 break;
6724 case 'b':
6725 antenna |= ANTENNA_B;
6726 break;
6727 }
6728 }
6729 padapter->mppriv.antenna_tx = antenna;
6730
6731 Hal_SetAntenna(padapter);
6732
6733 wrqu->length = strlen(extra) + 1;
6734 kfree(input);
6735 return 0;
6736 }
6737
6738 static int rtw_mp_ant_rx(struct net_device *dev,
6739 struct iw_request_info *info,
6740 struct iw_point *wrqu, char *extra)
6741 {
6742 u8 i;
6743 u16 antenna = 0;
6744 char *input = kmalloc(wrqu->length, GFP_KERNEL);
6745 struct adapter *padapter = rtw_netdev_priv(dev);
6746
6747 if (!input)
6748 return -ENOMEM;
6749 if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6750 kfree(input);
6751 return -EFAULT;
6752 }
6753 memset(extra, 0, wrqu->length);
6754
6755 sprintf(extra, "switch Rx antenna to %s", input);
6756
6757 for (i = 0; i < strlen(input); i++) {
6758 switch (input[i]) {
6759 case 'a':
6760 antenna |= ANTENNA_A;
6761 break;
6762 case 'b':
6763 antenna |= ANTENNA_B;
6764 break;
6765 }
6766 }
6767
6768 padapter->mppriv.antenna_rx = antenna;
6769 Hal_SetAntenna(padapter);
6770 wrqu->length = strlen(extra);
6771 kfree(input);
6772 return 0;
6773 }
6774
6775 static int rtw_mp_ctx(struct net_device *dev,
6776 struct iw_request_info *info,
6777 struct iw_point *wrqu, char *extra)
6778 {
6779 u32 pkTx = 1, countPkTx = 1, cotuTx = 1, CarrSprTx = 1, scTx = 1, sgleTx = 1, stop = 1;
6780 u32 bStartTest = 1;
6781 u32 count = 0;
6782 int rv;
6783 struct mp_priv *pmp_priv;
6784 struct pkt_attrib *pattrib;
6785
6786 struct adapter *padapter = rtw_netdev_priv(dev);
6787
6788 pmp_priv = &padapter->mppriv;
6789
6790 if (copy_from_user(extra, wrqu->pointer, wrqu->length))
6791 return -EFAULT;
6792
6793 DBG_88E("%s: in =%s\n", __func__, extra);
6794
6795 countPkTx = strncmp(extra, "count=", 6); /* strncmp true is 0 */
6796 cotuTx = strncmp(extra, "background", 20);
6797 CarrSprTx = strncmp(extra, "background, cs", 20);
6798 scTx = strncmp(extra, "background, sc", 20);
6799 sgleTx = strncmp(extra, "background, stone", 20);
6800 pkTx = strncmp(extra, "background, pkt", 20);
6801 stop = strncmp(extra, "stop", 4);
6802 rv = sscanf(extra, "count =%d, pkt", &count);
6803 if (rv != 2)
6804 return -EINVAL;
6805
6806 memset(extra, '\0', sizeof(*extra));
6807
6808 if (stop == 0) {
6809 bStartTest = 0; /* To set Stop */
6810 pmp_priv->tx.stop = 1;
6811 sprintf(extra, "Stop continuous Tx");
6812 } else {
6813 bStartTest = 1;
6814 if (pmp_priv->mode != MP_ON) {
6815 if (pmp_priv->tx.stop != 1) {
6816 DBG_88E("%s: MP_MODE != ON %d\n", __func__, pmp_priv->mode);
6817 return -EFAULT;
6818 }
6819 }
6820 }
6821
6822 if (pkTx == 0 || countPkTx == 0)
6823 pmp_priv->mode = MP_PACKET_TX;
6824 if (sgleTx == 0)
6825 pmp_priv->mode = MP_SINGLE_TONE_TX;
6826 if (cotuTx == 0)
6827 pmp_priv->mode = MP_CONTINUOUS_TX;
6828 if (CarrSprTx == 0)
6829 pmp_priv->mode = MP_CARRIER_SUPPRISSION_TX;
6830 if (scTx == 0)
6831 pmp_priv->mode = MP_SINGLE_CARRIER_TX;
6832
6833 switch (pmp_priv->mode) {
6834 case MP_PACKET_TX:
6835 if (bStartTest == 0) {
6836 pmp_priv->tx.stop = 1;
6837 pmp_priv->mode = MP_ON;
6838 sprintf(extra, "Stop continuous Tx");
6839 } else if (pmp_priv->tx.stop == 1) {
6840 sprintf(extra, "Start continuous DA = ffffffffffff len = 1500 count =%u,\n", count);
6841 pmp_priv->tx.stop = 0;
6842 pmp_priv->tx.count = count;
6843 pmp_priv->tx.payload = 2;
6844 pattrib = &pmp_priv->tx.attrib;
6845 pattrib->pktlen = 1500;
6846 memset(pattrib->dst, 0xFF, ETH_ALEN);
6847 SetPacketTx(padapter);
6848 } else {
6849 return -EFAULT;
6850 }
6851 wrqu->length = strlen(extra);
6852 return 0;
6853 case MP_SINGLE_TONE_TX:
6854 if (bStartTest != 0)
6855 sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
6856 Hal_SetSingleToneTx(padapter, (u8)bStartTest);
6857 break;
6858 case MP_CONTINUOUS_TX:
6859 if (bStartTest != 0)
6860 sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
6861 Hal_SetContinuousTx(padapter, (u8)bStartTest);
6862 break;
6863 case MP_CARRIER_SUPPRISSION_TX:
6864 if (bStartTest != 0) {
6865 if (pmp_priv->rateidx <= MPT_RATE_11M) {
6866 sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
6867 Hal_SetCarrierSuppressionTx(padapter, (u8)bStartTest);
6868 } else {
6869 sprintf(extra, "Specify carrier suppression but not CCK rate");
6870 }
6871 }
6872 break;
6873 case MP_SINGLE_CARRIER_TX:
6874 if (bStartTest != 0)
6875 sprintf(extra, "Start continuous DA = ffffffffffff len = 1500\n infinite = yes.");
6876 Hal_SetSingleCarrierTx(padapter, (u8)bStartTest);
6877 break;
6878 default:
6879 sprintf(extra, "Error! Continuous-Tx is not on-going.");
6880 return -EFAULT;
6881 }
6882
6883 if (bStartTest == 1 && pmp_priv->mode != MP_ON) {
6884 struct mp_priv *pmp_priv = &padapter->mppriv;
6885 if (pmp_priv->tx.stop == 0) {
6886 pmp_priv->tx.stop = 1;
6887 msleep(5);
6888 }
6889 pmp_priv->tx.stop = 0;
6890 pmp_priv->tx.count = 1;
6891 SetPacketTx(padapter);
6892 } else {
6893 pmp_priv->mode = MP_ON;
6894 }
6895
6896 wrqu->length = strlen(extra);
6897 return 0;
6898 }
6899
6900 static int rtw_mp_arx(struct net_device *dev,
6901 struct iw_request_info *info,
6902 struct iw_point *wrqu, char *extra)
6903 {
6904 u8 bStartRx = 0, bStopRx = 0, bQueryPhy;
6905 u32 cckok = 0, cckcrc = 0, ofdmok = 0, ofdmcrc = 0, htok = 0, htcrc = 0, OFDM_FA = 0, CCK_FA = 0;
6906 char *input = kmalloc(wrqu->length, GFP_KERNEL);
6907 struct adapter *padapter = rtw_netdev_priv(dev);
6908
6909 if (!input)
6910 return -ENOMEM;
6911
6912 if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6913 kfree(input);
6914 return -EFAULT;
6915 }
6916 DBG_88E("%s: %s\n", __func__, input);
6917
6918 bStartRx = (strncmp(input, "start", 5) == 0) ? 1 : 0; /* strncmp true is 0 */
6919 bStopRx = (strncmp(input, "stop", 4) == 0) ? 1 : 0; /* strncmp true is 0 */
6920 bQueryPhy = (strncmp(input, "phy", 3) == 0) ? 1 : 0; /* strncmp true is 0 */
6921
6922 if (bStartRx) {
6923 sprintf(extra, "start");
6924 SetPacketRx(padapter, bStartRx);
6925 } else if (bStopRx) {
6926 SetPacketRx(padapter, 0);
6927 sprintf(extra, "Received packet OK:%d CRC error:%d", padapter->mppriv.rx_pktcount, padapter->mppriv.rx_crcerrpktcount);
6928 } else if (bQueryPhy) {
6929 /*
6930 OFDM FA
6931 RegCF0[15:0]
6932 RegCF2[31:16]
6933 RegDA0[31:16]
6934 RegDA4[15:0]
6935 RegDA4[31:16]
6936 RegDA8[15:0]
6937 CCK FA
6938 (RegA5B<<8) | RegA5C
6939 */
6940 cckok = read_bbreg(padapter, 0xf88, 0xffffffff);
6941 cckcrc = read_bbreg(padapter, 0xf84, 0xffffffff);
6942 ofdmok = read_bbreg(padapter, 0xf94, 0x0000FFFF);
6943 ofdmcrc = read_bbreg(padapter, 0xf94, 0xFFFF0000);
6944 htok = read_bbreg(padapter, 0xf90, 0x0000FFFF);
6945 htcrc = read_bbreg(padapter, 0xf90, 0xFFFF0000);
6946
6947 OFDM_FA = read_bbreg(padapter, 0xcf0, 0x0000FFFF);
6948 OFDM_FA = read_bbreg(padapter, 0xcf2, 0xFFFF0000);
6949 OFDM_FA = read_bbreg(padapter, 0xda0, 0xFFFF0000);
6950 OFDM_FA = read_bbreg(padapter, 0xda4, 0x0000FFFF);
6951 OFDM_FA = read_bbreg(padapter, 0xda4, 0xFFFF0000);
6952 OFDM_FA = read_bbreg(padapter, 0xda8, 0x0000FFFF);
6953 CCK_FA = (usb_read8(padapter, 0xa5b)<<8) | (usb_read8(padapter, 0xa5c));
6954
6955 sprintf(extra, "Phy Received packet OK:%d CRC error:%d FA Counter: %d", cckok+ofdmok+htok, cckcrc+ofdmcrc+htcrc, OFDM_FA+CCK_FA);
6956 }
6957 wrqu->length = strlen(extra) + 1;
6958 kfree(input);
6959 return 0;
6960 }
6961
6962 static int rtw_mp_trx_query(struct net_device *dev,
6963 struct iw_request_info *info,
6964 struct iw_point *wrqu, char *extra)
6965 {
6966 u32 txok, txfail, rxok, rxfail;
6967 struct adapter *padapter = rtw_netdev_priv(dev);
6968
6969 txok = padapter->mppriv.tx.sended;
6970 txfail = 0;
6971 rxok = padapter->mppriv.rx_pktcount;
6972 rxfail = padapter->mppriv.rx_crcerrpktcount;
6973
6974 memset(extra, '\0', 128);
6975
6976 sprintf(extra, "Tx OK:%d, Tx Fail:%d, Rx OK:%d, CRC error:%d ", txok, txfail, rxok, rxfail);
6977
6978 wrqu->length = strlen(extra)+1;
6979
6980 return 0;
6981 }
6982
6983 static int rtw_mp_pwrtrk(struct net_device *dev,
6984 struct iw_request_info *info,
6985 struct iw_point *wrqu, char *extra)
6986 {
6987 u8 enable;
6988 u32 thermal;
6989 struct adapter *padapter = rtw_netdev_priv(dev);
6990 char *input = kmalloc(wrqu->length, GFP_KERNEL);
6991 int ret = 0;
6992
6993 if (!input)
6994 return -ENOMEM;
6995 if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
6996 ret = -EFAULT;
6997 goto exit;
6998 }
6999 memset(extra, 0, wrqu->length);
7000
7001 enable = 1;
7002 if (wrqu->length > 1) {/* not empty string */
7003 if (strncmp(input, "stop", 4) == 0) {
7004 enable = 0;
7005 sprintf(extra, "mp tx power tracking stop");
7006 } else if (sscanf(input, "ther =%d", &thermal)) {
7007 ret = Hal_SetThermalMeter(padapter, (u8)thermal);
7008 if (ret == _FAIL) {
7009 ret = -EPERM;
7010 goto exit;
7011 }
7012 sprintf(extra, "mp tx power tracking start, target value =%d ok ", thermal);
7013 } else {
7014 ret = -EINVAL;
7015 goto exit;
7016 }
7017 }
7018
7019 ret = Hal_SetPowerTracking(padapter, enable);
7020 if (ret == _FAIL) {
7021 ret = -EPERM;
7022 goto exit;
7023 }
7024
7025 wrqu->length = strlen(extra);
7026
7027 exit:
7028 kfree(input);
7029 return ret;
7030 }
7031
7032 static int rtw_mp_psd(struct net_device *dev,
7033 struct iw_request_info *info,
7034 struct iw_point *wrqu, char *extra)
7035 {
7036 struct adapter *padapter = rtw_netdev_priv(dev);
7037 char *input = kmalloc(wrqu->length, GFP_KERNEL);
7038
7039 if (!input)
7040 return -ENOMEM;
7041 if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
7042 kfree(input);
7043 return -EFAULT;
7044 }
7045
7046 strcpy(extra, input);
7047
7048 wrqu->length = mp_query_psd(padapter, extra);
7049 kfree(input);
7050 return 0;
7051 }
7052
7053 static int rtw_mp_thermal(struct net_device *dev,
7054 struct iw_request_info *info,
7055 struct iw_point *wrqu, char *extra)
7056 {
7057 u8 val;
7058 u16 bwrite = 1;
7059 u16 addr = EEPROM_THERMAL_METER_88E;
7060
7061 u16 cnt = 1;
7062 u16 max_available_size = 0;
7063 struct adapter *padapter = rtw_netdev_priv(dev);
7064
7065 if (copy_from_user(extra, wrqu->pointer, wrqu->length))
7066 return -EFAULT;
7067
7068 bwrite = strncmp(extra, "write", 6); /* strncmp true is 0 */
7069
7070 Hal_GetThermalMeter(padapter, &val);
7071
7072 if (bwrite == 0) {
7073 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size);
7074 if (2 > max_available_size) {
7075 DBG_88E("no available efuse!\n");
7076 return -EFAULT;
7077 }
7078 if (rtw_efuse_map_write(padapter, addr, cnt, &val) == _FAIL) {
7079 DBG_88E("rtw_efuse_map_write error\n");
7080 return -EFAULT;
7081 } else {
7082 sprintf(extra, " efuse write ok :%d", val);
7083 }
7084 } else {
7085 sprintf(extra, "%d", val);
7086 }
7087 wrqu->length = strlen(extra);
7088
7089 return 0;
7090 }
7091
7092 static int rtw_mp_reset_stats(struct net_device *dev,
7093 struct iw_request_info *info,
7094 struct iw_point *wrqu, char *extra)
7095 {
7096 struct mp_priv *pmp_priv;
7097 struct adapter *padapter = rtw_netdev_priv(dev);
7098
7099 pmp_priv = &padapter->mppriv;
7100
7101 pmp_priv->tx.sended = 0;
7102 pmp_priv->tx_pktcount = 0;
7103 pmp_priv->rx_pktcount = 0;
7104 pmp_priv->rx_crcerrpktcount = 0;
7105
7106 /* reset phy counter */
7107 write_bbreg(padapter, 0xf14, BIT16, 0x1);
7108 msleep(10);
7109 write_bbreg(padapter, 0xf14, BIT16, 0x0);
7110
7111 return 0;
7112 }
7113
7114 static int rtw_mp_dump(struct net_device *dev,
7115 struct iw_request_info *info,
7116 struct iw_point *wrqu, char *extra)
7117 {
7118 u32 value;
7119 u8 rf_type, path_nums = 0;
7120 u32 i, j = 1, path;
7121 struct adapter *padapter = rtw_netdev_priv(dev);
7122
7123 if (strncmp(extra, "all", 4) == 0) {
7124 DBG_88E("\n ======= MAC REG =======\n");
7125 for (i = 0x0; i < 0x300; i += 4) {
7126 if (j%4 == 1)
7127 DBG_88E("0x%02x", i);
7128 DBG_88E(" 0x%08x ", usb_read32(padapter, i));
7129 if ((j++)%4 == 0)
7130 DBG_88E("\n");
7131 }
7132 for (i = 0x400; i < 0x1000; i += 4) {
7133 if (j%4 == 1)
7134 DBG_88E("0x%02x", i);
7135 DBG_88E(" 0x%08x ", usb_read32(padapter, i));
7136 if ((j++)%4 == 0)
7137 DBG_88E("\n");
7138 }
7139
7140 j = 1;
7141 rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
7142
7143 DBG_88E("\n ======= RF REG =======\n");
7144 if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type))
7145 path_nums = 1;
7146 else
7147 path_nums = 2;
7148
7149 for (path = 0; path < path_nums; path++) {
7150 for (i = 0; i < 0x34; i++) {
7151 value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff);
7152 if (j%4 == 1)
7153 DBG_88E("0x%02x ", i);
7154 DBG_88E(" 0x%08x ", value);
7155 if ((j++)%4 == 0)
7156 DBG_88E("\n");
7157 }
7158 }
7159 }
7160 return 0;
7161 }
7162
7163 static int rtw_mp_phypara(struct net_device *dev,
7164 struct iw_request_info *info,
7165 struct iw_point *wrqu, char *extra)
7166 {
7167 char *input = kmalloc(wrqu->length, GFP_KERNEL);
7168 u32 valxcap;
7169 int rv;
7170
7171 if (!input)
7172 return -ENOMEM;
7173 if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
7174 kfree(input);
7175 return -EFAULT;
7176 }
7177
7178 DBG_88E("%s:iwpriv in =%s\n", __func__, input);
7179
7180 rv = sscanf(input, "xcap =%d", &valxcap);
7181 if (rv != 1) {
7182 kfree(input);
7183 return -EINVAL;
7184 }
7185
7186 kfree(input);
7187 return 0;
7188 }
7189
7190 static int rtw_mp_SetRFPath(struct net_device *dev,
7191 struct iw_request_info *info,
7192 union iwreq_data *wrqu, char *extra)
7193 {
7194 struct adapter *padapter = rtw_netdev_priv(dev);
7195 char *input = kmalloc(wrqu->data.length, GFP_KERNEL);
7196 u8 bMain = 1, bTurnoff = 1;
7197 int ret = 0;
7198
7199 if (!input)
7200 return -ENOMEM;
7201 if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length)) {
7202 ret = -EFAULT;
7203 goto exit;
7204 }
7205 DBG_88E("%s:iwpriv in =%s\n", __func__, input);
7206
7207 bMain = strncmp(input, "1", 2); /* strncmp true is 0 */
7208 bTurnoff = strncmp(input, "0", 3); /* strncmp true is 0 */
7209
7210 if (bMain == 0) {
7211 MP_PHY_SetRFPathSwitch(padapter, true);
7212 DBG_88E("%s:PHY_SetRFPathSwitch = true\n", __func__);
7213 } else if (bTurnoff == 0) {
7214 MP_PHY_SetRFPathSwitch(padapter, false);
7215 DBG_88E("%s:PHY_SetRFPathSwitch = false\n", __func__);
7216 }
7217
7218 exit:
7219 kfree(input);
7220 return ret;
7221 }
7222
7223 static int rtw_mp_QueryDrv(struct net_device *dev,
7224 struct iw_request_info *info,
7225 union iwreq_data *wrqu, char *extra)
7226 {
7227 struct adapter *padapter = rtw_netdev_priv(dev);
7228 char *input = kmalloc(wrqu->data.length, GFP_KERNEL);
7229 u8 qAutoLoad = 1;
7230 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
7231 int ret = 0;
7232
7233 if (!input)
7234 return -ENOMEM;
7235
7236 if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length)) {
7237 ret = -EFAULT;
7238 goto exit;
7239 }
7240 DBG_88E("%s:iwpriv in =%s\n", __func__, input);
7241
7242 qAutoLoad = strncmp(input, "autoload", 8); /* strncmp true is 0 */
7243
7244 if (qAutoLoad == 0) {
7245 DBG_88E("%s:qAutoLoad\n", __func__);
7246
7247 if (pEEPROM->bautoload_fail_flag)
7248 sprintf(extra, "fail");
7249 else
7250 sprintf(extra, "ok");
7251 }
7252 wrqu->data.length = strlen(extra) + 1;
7253
7254 exit:
7255 kfree(input);
7256 return ret;
7257 }
7258
7259 static int rtw_mp_set(struct net_device *dev,
7260 struct iw_request_info *info,
7261 union iwreq_data *wdata, char *extra)
7262 {
7263 struct iw_point *wrqu = (struct iw_point *)wdata;
7264 u32 subcmd = wrqu->flags;
7265 struct adapter *padapter = rtw_netdev_priv(dev);
7266
7267 if (padapter == NULL)
7268 return -ENETDOWN;
7269
7270 if (extra == NULL) {
7271 wrqu->length = 0;
7272 return -EIO;
7273 }
7274
7275 switch (subcmd) {
7276 case MP_START:
7277 DBG_88E("set case mp_start\n");
7278 rtw_mp_start(dev, info, wrqu, extra);
7279 break;
7280 case MP_STOP:
7281 DBG_88E("set case mp_stop\n");
7282 rtw_mp_stop(dev, info, wrqu, extra);
7283 break;
7284 case MP_BANDWIDTH:
7285 DBG_88E("set case mp_bandwidth\n");
7286 rtw_mp_bandwidth(dev, info, wrqu, extra);
7287 break;
7288 case MP_RESET_STATS:
7289 DBG_88E("set case MP_RESET_STATS\n");
7290 rtw_mp_reset_stats(dev, info, wrqu, extra);
7291 break;
7292 case MP_SetRFPathSwh:
7293 DBG_88E("set MP_SetRFPathSwitch\n");
7294 rtw_mp_SetRFPath(dev, info, wdata, extra);
7295 break;
7296 case CTA_TEST:
7297 DBG_88E("set CTA_TEST\n");
7298 rtw_cta_test_start(dev, info, wdata, extra);
7299 break;
7300 }
7301
7302 return 0;
7303 }
7304
7305 static int rtw_mp_get(struct net_device *dev,
7306 struct iw_request_info *info,
7307 union iwreq_data *wdata, char *extra)
7308 {
7309 struct iw_point *wrqu = (struct iw_point *)wdata;
7310 u32 subcmd = wrqu->flags;
7311 struct adapter *padapter = rtw_netdev_priv(dev);
7312
7313 if (padapter == NULL)
7314 return -ENETDOWN;
7315 if (extra == NULL) {
7316 wrqu->length = 0;
7317 return -EIO;
7318 }
7319
7320 switch (subcmd) {
7321 case WRITE_REG:
7322 rtw_mp_write_reg(dev, info, wrqu, extra);
7323 break;
7324 case WRITE_RF:
7325 rtw_mp_write_rf(dev, info, wrqu, extra);
7326 break;
7327 case MP_PHYPARA:
7328 DBG_88E("mp_get MP_PHYPARA\n");
7329 rtw_mp_phypara(dev, info, wrqu, extra);
7330 break;
7331 case MP_CHANNEL:
7332 DBG_88E("set case mp_channel\n");
7333 rtw_mp_channel(dev, info, wrqu, extra);
7334 break;
7335 case READ_REG:
7336 DBG_88E("mp_get READ_REG\n");
7337 rtw_mp_read_reg(dev, info, wrqu, extra);
7338 break;
7339 case READ_RF:
7340 DBG_88E("mp_get READ_RF\n");
7341 rtw_mp_read_rf(dev, info, wrqu, extra);
7342 break;
7343 case MP_RATE:
7344 DBG_88E("set case mp_rate\n");
7345 rtw_mp_rate(dev, info, wrqu, extra);
7346 break;
7347 case MP_TXPOWER:
7348 DBG_88E("set case MP_TXPOWER\n");
7349 rtw_mp_txpower(dev, info, wrqu, extra);
7350 break;
7351 case MP_ANT_TX:
7352 DBG_88E("set case MP_ANT_TX\n");
7353 rtw_mp_ant_tx(dev, info, wrqu, extra);
7354 break;
7355 case MP_ANT_RX:
7356 DBG_88E("set case MP_ANT_RX\n");
7357 rtw_mp_ant_rx(dev, info, wrqu, extra);
7358 break;
7359 case MP_QUERY:
7360 rtw_mp_trx_query(dev, info, wrqu, extra);
7361 break;
7362 case MP_CTX:
7363 DBG_88E("set case MP_CTX\n");
7364 rtw_mp_ctx(dev, info, wrqu, extra);
7365 break;
7366 case MP_ARX:
7367 DBG_88E("set case MP_ARX\n");
7368 rtw_mp_arx(dev, info, wrqu, extra);
7369 break;
7370 case EFUSE_GET:
7371 DBG_88E("efuse get EFUSE_GET\n");
7372 rtw_mp_efuse_get(dev, info, wdata, extra);
7373 break;
7374 case MP_DUMP:
7375 DBG_88E("set case MP_DUMP\n");
7376 rtw_mp_dump(dev, info, wrqu, extra);
7377 break;
7378 case MP_PSD:
7379 DBG_88E("set case MP_PSD\n");
7380 rtw_mp_psd(dev, info, wrqu, extra);
7381 break;
7382 case MP_THER:
7383 DBG_88E("set case MP_THER\n");
7384 rtw_mp_thermal(dev, info, wrqu, extra);
7385 break;
7386 case MP_QueryDrvStats:
7387 DBG_88E("mp_get MP_QueryDrvStats\n");
7388 rtw_mp_QueryDrv (dev, info, wdata, extra);
7389 break;
7390 case MP_PWRTRK:
7391 DBG_88E("set case MP_PWRTRK\n");
7392 rtw_mp_pwrtrk(dev, info, wrqu, extra);
7393 break;
7394 case EFUSE_SET:
7395 DBG_88E("set case efuse set\n");
7396 rtw_mp_efuse_set(dev, info, wdata, extra);
7397 break;
7398 }
7399
7400 msleep(10); /* delay 5ms for sending pkt before exit adb shell operation */
7401 return 0;
7402 }
7403
7404 static int rtw_tdls(struct net_device *dev,
7405 struct iw_request_info *info,
7406 union iwreq_data *wrqu, char *extra)
7407 {
7408 return 0;
7409 }
7410
7411 static int rtw_tdls_get(struct net_device *dev,
7412 struct iw_request_info *info,
7413 union iwreq_data *wrqu, char *extra)
7414 {
7415 return 0;
7416 }
7417
7418 static int rtw_test(
7419 struct net_device *dev,
7420 struct iw_request_info *info,
7421 union iwreq_data *wrqu, char *extra)
7422 {
7423 u32 len;
7424 u8 *pbuf, *pch;
7425 char *ptmp;
7426 u8 *delim = ",";
7427
7428 DBG_88E("+%s\n", __func__);
7429 len = wrqu->data.length;
7430
7431 pbuf = (u8 *)rtw_zmalloc(len);
7432 if (pbuf == NULL) {
7433 DBG_88E("%s: no memory!\n", __func__);
7434 return -ENOMEM;
7435 }
7436
7437 if (copy_from_user(pbuf, wrqu->data.pointer, len)) {
7438 kfree(pbuf);
7439 DBG_88E("%s: copy from user fail!\n", __func__);
7440 return -EFAULT;
7441 }
7442 DBG_88E("%s: string =\"%s\"\n", __func__, pbuf);
7443
7444 ptmp = (char *)pbuf;
7445 pch = strsep(&ptmp, delim);
7446 if ((pch == NULL) || (strlen(pch) == 0)) {
7447 kfree(pbuf);
7448 DBG_88E("%s: parameter error(level 1)!\n", __func__);
7449 return -EFAULT;
7450 }
7451 kfree(pbuf);
7452 return 0;
7453 }
7454
7455 static iw_handler rtw_handlers[] = {
7456 NULL, /* SIOCSIWCOMMIT */
7457 rtw_wx_get_name, /* SIOCGIWNAME */
7458 dummy, /* SIOCSIWNWID */
7459 dummy, /* SIOCGIWNWID */
7460 rtw_wx_set_freq, /* SIOCSIWFREQ */
7461 rtw_wx_get_freq, /* SIOCGIWFREQ */
7462 rtw_wx_set_mode, /* SIOCSIWMODE */
7463 rtw_wx_get_mode, /* SIOCGIWMODE */
7464 dummy, /* SIOCSIWSENS */
7465 rtw_wx_get_sens, /* SIOCGIWSENS */
7466 NULL, /* SIOCSIWRANGE */
7467 rtw_wx_get_range, /* SIOCGIWRANGE */
7468 rtw_wx_set_priv, /* SIOCSIWPRIV */
7469 NULL, /* SIOCGIWPRIV */
7470 NULL, /* SIOCSIWSTATS */
7471 NULL, /* SIOCGIWSTATS */
7472 dummy, /* SIOCSIWSPY */
7473 dummy, /* SIOCGIWSPY */
7474 NULL, /* SIOCGIWTHRSPY */
7475 NULL, /* SIOCWIWTHRSPY */
7476 rtw_wx_set_wap, /* SIOCSIWAP */
7477 rtw_wx_get_wap, /* SIOCGIWAP */
7478 rtw_wx_set_mlme, /* request MLME operation; uses struct iw_mlme */
7479 dummy, /* SIOCGIWAPLIST -- depricated */
7480 rtw_wx_set_scan, /* SIOCSIWSCAN */
7481 rtw_wx_get_scan, /* SIOCGIWSCAN */
7482 rtw_wx_set_essid, /* SIOCSIWESSID */
7483 rtw_wx_get_essid, /* SIOCGIWESSID */
7484 dummy, /* SIOCSIWNICKN */
7485 rtw_wx_get_nick, /* SIOCGIWNICKN */
7486 NULL, /* -- hole -- */
7487 NULL, /* -- hole -- */
7488 rtw_wx_set_rate, /* SIOCSIWRATE */
7489 rtw_wx_get_rate, /* SIOCGIWRATE */
7490 rtw_wx_set_rts, /* SIOCSIWRTS */
7491 rtw_wx_get_rts, /* SIOCGIWRTS */
7492 rtw_wx_set_frag, /* SIOCSIWFRAG */
7493 rtw_wx_get_frag, /* SIOCGIWFRAG */
7494 dummy, /* SIOCSIWTXPOW */
7495 dummy, /* SIOCGIWTXPOW */
7496 dummy, /* SIOCSIWRETRY */
7497 rtw_wx_get_retry, /* SIOCGIWRETRY */
7498 rtw_wx_set_enc, /* SIOCSIWENCODE */
7499 rtw_wx_get_enc, /* SIOCGIWENCODE */
7500 dummy, /* SIOCSIWPOWER */
7501 rtw_wx_get_power, /* SIOCGIWPOWER */
7502 NULL, /*---hole---*/
7503 NULL, /*---hole---*/
7504 rtw_wx_set_gen_ie, /* SIOCSIWGENIE */
7505 NULL, /* SIOCGWGENIE */
7506 rtw_wx_set_auth, /* SIOCSIWAUTH */
7507 NULL, /* SIOCGIWAUTH */
7508 rtw_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
7509 NULL, /* SIOCGIWENCODEEXT */
7510 rtw_wx_set_pmkid, /* SIOCSIWPMKSA */
7511 NULL, /*---hole---*/
7512 };
7513
7514 static const struct iw_priv_args rtw_private_args[] = {
7515 {
7516 SIOCIWFIRSTPRIV + 0x0,
7517 IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write"
7518 },
7519 {
7520 SIOCIWFIRSTPRIV + 0x1,
7521 IW_PRIV_TYPE_CHAR | 0x7FF,
7522 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read"
7523 },
7524 {
7525 SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
7526 },
7527 {
7528 SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
7529 },
7530 {
7531 SIOCIWFIRSTPRIV + 0x4,
7532 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
7533 },
7534 {
7535 SIOCIWFIRSTPRIV + 0x5,
7536 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid"
7537 },
7538 {
7539 SIOCIWFIRSTPRIV + 0x6,
7540 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
7541 },
7542 {
7543 SIOCIWFIRSTPRIV + 0x7,
7544 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "get_sensitivity"
7545 },
7546 {
7547 SIOCIWFIRSTPRIV + 0x8,
7548 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_prob_req_ie"
7549 },
7550 {
7551 SIOCIWFIRSTPRIV + 0x9,
7552 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_assoc_req_ie"
7553 },
7554
7555 {
7556 SIOCIWFIRSTPRIV + 0xA,
7557 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan"
7558 },
7559
7560 {
7561 SIOCIWFIRSTPRIV + 0xB,
7562 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg"
7563 },
7564 {
7565 SIOCIWFIRSTPRIV + 0xC,
7566 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw"
7567 },
7568 {
7569 SIOCIWFIRSTPRIV + 0xD,
7570 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr"
7571 },
7572 {
7573 SIOCIWFIRSTPRIV + 0x10,
7574 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, 0, "p2p_set"
7575 },
7576 {
7577 SIOCIWFIRSTPRIV + 0x11,
7578 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN, "p2p_get"
7579 },
7580 {
7581 SIOCIWFIRSTPRIV + 0x12,
7582 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IFNAMSIZ, "p2p_get2"
7583 },
7584 {SIOCIWFIRSTPRIV + 0x13, IW_PRIV_TYPE_CHAR | 128, 0, "NULL"},
7585 {
7586 SIOCIWFIRSTPRIV + 0x14,
7587 IW_PRIV_TYPE_CHAR | 64, 0, "tdls"
7588 },
7589 {
7590 SIOCIWFIRSTPRIV + 0x15,
7591 IW_PRIV_TYPE_CHAR | P2P_PRIVATE_IOCTL_SET_LEN, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | P2P_PRIVATE_IOCTL_SET_LEN, "tdls_get"
7592 },
7593 {
7594 SIOCIWFIRSTPRIV + 0x16,
7595 IW_PRIV_TYPE_CHAR | 64, 0, "pm_set"
7596 },
7597
7598 {SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ, 0, "rereg_nd_name"},
7599
7600 {SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0, "efuse_set"},
7601 {SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
7602 {SIOCIWFIRSTPRIV + 0x1D, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "test"
7603 },
7604
7605 {SIOCIWFIRSTPRIV + 0x0E, IW_PRIV_TYPE_CHAR | 1024, 0, ""}, /* set */
7606 {SIOCIWFIRSTPRIV + 0x0F, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, ""},/* get */
7607 /* --- sub-ioctls definitions --- */
7608
7609 {MP_START, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_start"}, /* set */
7610 {MP_PHYPARA, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_phypara"},/* get */
7611 {MP_STOP, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_stop"}, /* set */
7612 {MP_CHANNEL, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_channel"},/* get */
7613 {MP_BANDWIDTH, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_bandwidth"}, /* set */
7614 {MP_RATE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate"},/* get */
7615 {MP_RESET_STATS, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_reset_stats"},
7616 {MP_QUERY, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_query"}, /* get */
7617 {READ_REG, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_reg"},
7618 {MP_RATE, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_rate"},
7619 {READ_RF, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "read_rf"},
7620 {MP_PSD, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_psd"},
7621 {MP_DUMP, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_dump"},
7622 {MP_TXPOWER, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_txpower"},
7623 {MP_ANT_TX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_tx"},
7624 {MP_ANT_RX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ant_rx"},
7625 {WRITE_REG, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_reg"},
7626 {WRITE_RF, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "write_rf"},
7627 {MP_CTX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ctx"},
7628 {MP_ARX, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_arx"},
7629 {MP_THER, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_ther"},
7630 {EFUSE_SET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_set"},
7631 {EFUSE_GET, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
7632 {MP_PWRTRK, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_pwrtrk"},
7633 {MP_QueryDrvStats, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "mp_drvquery"},
7634 {MP_IOCTL, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_ioctl"}, /* mp_ioctl */
7635 {MP_SetRFPathSwh, IW_PRIV_TYPE_CHAR | 1024, 0, "mp_setrfpath"},
7636 {CTA_TEST, IW_PRIV_TYPE_CHAR | 1024, 0, "cta_test"},
7637 };
7638
7639 static iw_handler rtw_private_handler[] = {
7640 rtw_wx_write32, /* 0x00 */
7641 rtw_wx_read32, /* 0x01 */
7642 rtw_drvext_hdl, /* 0x02 */
7643 rtw_mp_ioctl_hdl, /* 0x03 */
7644
7645 /* for MM DTV platform */
7646 rtw_get_ap_info, /* 0x04 */
7647
7648 rtw_set_pid, /* 0x05 */
7649 rtw_wps_start, /* 0x06 */
7650
7651 rtw_wx_get_sensitivity, /* 0x07 */
7652 rtw_wx_set_mtk_wps_probe_ie, /* 0x08 */
7653 rtw_wx_set_mtk_wps_ie, /* 0x09 */
7654
7655 /* Set Channel depend on the country code */
7656 rtw_wx_set_channel_plan, /* 0x0A */
7657
7658 rtw_dbg_port, /* 0x0B */
7659 rtw_wx_write_rf, /* 0x0C */
7660 rtw_wx_read_rf, /* 0x0D */
7661
7662 rtw_mp_set, /* 0x0E */
7663 rtw_mp_get, /* 0x0F */
7664 rtw_p2p_set, /* 0x10 */
7665 rtw_p2p_get, /* 0x11 */
7666 rtw_p2p_get2, /* 0x12 */
7667
7668 NULL, /* 0x13 */
7669 rtw_tdls, /* 0x14 */
7670 rtw_tdls_get, /* 0x15 */
7671
7672 rtw_pm_set, /* 0x16 */
7673 rtw_wx_priv_null, /* 0x17 */
7674 rtw_rereg_nd_name, /* 0x18 */
7675 rtw_wx_priv_null, /* 0x19 */
7676
7677 rtw_mp_efuse_set, /* 0x1A */
7678 rtw_mp_efuse_get, /* 0x1B */
7679 NULL, /* 0x1C is reserved for hostapd */
7680 rtw_test, /* 0x1D */
7681 };
7682
7683 static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
7684 {
7685 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
7686 struct iw_statistics *piwstats = &padapter->iwstats;
7687 int tmp_level = 0;
7688 int tmp_qual = 0;
7689 int tmp_noise = 0;
7690
7691 if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
7692 piwstats->qual.qual = 0;
7693 piwstats->qual.level = 0;
7694 piwstats->qual.noise = 0;
7695 } else {
7696 tmp_level = padapter->recvpriv.signal_strength;
7697 tmp_qual = padapter->recvpriv.signal_qual;
7698 tmp_noise = padapter->recvpriv.noise;
7699
7700 piwstats->qual.level = tmp_level;
7701 piwstats->qual.qual = tmp_qual;
7702 piwstats->qual.noise = tmp_noise;
7703 }
7704 piwstats->qual.updated = IW_QUAL_ALL_UPDATED;/* IW_QUAL_DBM; */
7705 return &padapter->iwstats;
7706 }
7707
7708 struct iw_handler_def rtw_handlers_def = {
7709 .standard = rtw_handlers,
7710 .num_standard = sizeof(rtw_handlers) / sizeof(iw_handler),
7711 .private = rtw_private_handler,
7712 .private_args = (struct iw_priv_args *)rtw_private_args,
7713 .num_private = sizeof(rtw_private_handler) / sizeof(iw_handler),
7714 .num_private_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args),
7715 .get_wireless_stats = rtw_get_wireless_stats,
7716 };
7717
7718 /* copy from net/wireless/wext.c start */
7719 /* ---------------------------------------------------------------- */
7720 /*
7721 * Calculate size of private arguments
7722 */
7723 static const char iw_priv_type_size[] = {
7724 0, /* IW_PRIV_TYPE_NONE */
7725 1, /* IW_PRIV_TYPE_BYTE */
7726 1, /* IW_PRIV_TYPE_CHAR */
7727 0, /* Not defined */
7728 sizeof(__u32), /* IW_PRIV_TYPE_INT */
7729 sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */
7730 sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */
7731 0, /* Not defined */
7732 };
7733
7734 static int get_priv_size(__u16 args)
7735 {
7736 int num = args & IW_PRIV_SIZE_MASK;
7737 int type = (args & IW_PRIV_TYPE_MASK) >> 12;
7738
7739 return num * iw_priv_type_size[type];
7740 }
7741 /* copy from net/wireless/wext.c end */
7742
7743 static int rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_data)
7744 {
7745 int err = 0;
7746 u8 *input = NULL;
7747 u32 input_len = 0;
7748 const char delim[] = " ";
7749 u8 *output = NULL;
7750 u32 output_len = 0;
7751 u32 count = 0;
7752 u8 *buffer = NULL;
7753 u32 buffer_len = 0;
7754 char *ptr = NULL;
7755 u8 cmdname[17] = {0}; /* IFNAMSIZ+1 */
7756 u32 cmdlen;
7757 s32 len;
7758 u8 *extra = NULL;
7759 u32 extra_size = 0;
7760 int rv;
7761
7762 s32 k;
7763 const iw_handler *priv; /* Private ioctl */
7764 const struct iw_priv_args *priv_args; /* Private ioctl description */
7765 u32 num_priv_args; /* Number of descriptions */
7766 iw_handler handler;
7767 int temp;
7768 int subcmd = 0; /* sub-ioctl index */
7769 int offset = 0; /* Space for sub-ioctl index */
7770
7771 union iwreq_data wdata;
7772
7773 memcpy(&wdata, wrq_data, sizeof(wdata));
7774
7775 input_len = wdata.data.length;
7776 input = rtw_zmalloc(input_len);
7777 if (NULL == input)
7778 return -ENOMEM;
7779 if (copy_from_user(input, wdata.data.pointer, input_len)) {
7780 err = -EFAULT;
7781 goto exit;
7782 }
7783 ptr = input;
7784 len = input_len;
7785
7786 rv = sscanf(ptr, "%16s", cmdname);
7787 if (rv != 1) {
7788 err = -EINVAL;
7789 goto exit;
7790 }
7791 cmdlen = strlen(cmdname);
7792 DBG_88E("%s: cmd =%s\n", __func__, cmdname);
7793
7794 /* skip command string */
7795 if (cmdlen > 0)
7796 cmdlen += 1; /* skip one space */
7797 ptr += cmdlen;
7798 len -= cmdlen;
7799 DBG_88E("%s: parameters =%s\n", __func__, ptr);
7800
7801 priv = rtw_private_handler;
7802 priv_args = rtw_private_args;
7803 num_priv_args = sizeof(rtw_private_args) / sizeof(struct iw_priv_args);
7804
7805 if (num_priv_args == 0) {
7806 err = -EOPNOTSUPP;
7807 goto exit;
7808 }
7809
7810 /* Search the correct ioctl */
7811 k = -1;
7812 while ((++k < num_priv_args) && strcmp(priv_args[k].name, cmdname));
7813
7814 /* If not found... */
7815 if (k == num_priv_args) {
7816 err = -EOPNOTSUPP;
7817 goto exit;
7818 }
7819
7820 /* Watch out for sub-ioctls ! */
7821 if (priv_args[k].cmd < SIOCDEVPRIVATE) {
7822 int j = -1;
7823
7824 /* Find the matching *real* ioctl */
7825 while ((++j < num_priv_args) && ((priv_args[j].name[0] != '\0') ||
7826 (priv_args[j].set_args != priv_args[k].set_args) ||
7827 (priv_args[j].get_args != priv_args[k].get_args)));
7828
7829 /* If not found... */
7830 if (j == num_priv_args) {
7831 err = -EINVAL;
7832 goto exit;
7833 }
7834
7835 /* Save sub-ioctl number */
7836 subcmd = priv_args[k].cmd;
7837 /* Reserve one int (simplify alignment issues) */
7838 offset = sizeof(__u32);
7839 /* Use real ioctl definition from now on */
7840 k = j;
7841 }
7842
7843 buffer = rtw_zmalloc(4096);
7844 if (NULL == buffer) {
7845 err = -ENOMEM;
7846 goto exit;
7847 }
7848
7849 /* If we have to set some data */
7850 if ((priv_args[k].set_args & IW_PRIV_TYPE_MASK) &&
7851 (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) {
7852 u8 *str;
7853
7854 switch (priv_args[k].set_args & IW_PRIV_TYPE_MASK) {
7855 case IW_PRIV_TYPE_BYTE:
7856 /* Fetch args */
7857 count = 0;
7858 do {
7859 str = strsep(&ptr, delim);
7860 if (NULL == str)
7861 break;
7862 sscanf(str, "%i", &temp);
7863 buffer[count++] = (u8)temp;
7864 } while (1);
7865 buffer_len = count;
7866 /* Number of args to fetch */
7867 wdata.data.length = count;
7868 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
7869 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
7870 break;
7871 case IW_PRIV_TYPE_INT:
7872 /* Fetch args */
7873 count = 0;
7874 do {
7875 str = strsep(&ptr, delim);
7876 if (NULL == str)
7877 break;
7878 sscanf(str, "%i", &temp);
7879 ((s32 *)buffer)[count++] = (s32)temp;
7880 } while (1);
7881 buffer_len = count * sizeof(s32);
7882 /* Number of args to fetch */
7883 wdata.data.length = count;
7884 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
7885 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
7886 break;
7887 case IW_PRIV_TYPE_CHAR:
7888 if (len > 0) {
7889 /* Size of the string to fetch */
7890 wdata.data.length = len;
7891 if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
7892 wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
7893
7894 /* Fetch string */
7895 memcpy(buffer, ptr, wdata.data.length);
7896 } else {
7897 wdata.data.length = 1;
7898 buffer[0] = '\0';
7899 }
7900 buffer_len = wdata.data.length;
7901 break;
7902 default:
7903 DBG_88E("%s: Not yet implemented...\n", __func__);
7904 err = -1;
7905 goto exit;
7906 }
7907
7908 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
7909 (wdata.data.length != (priv_args[k].set_args & IW_PRIV_SIZE_MASK))) {
7910 DBG_88E("%s: The command %s needs exactly %d argument(s)...\n",
7911 __func__, cmdname, priv_args[k].set_args & IW_PRIV_SIZE_MASK);
7912 err = -EINVAL;
7913 goto exit;
7914 }
7915 } else {
7916 /* if args to set */
7917 wdata.data.length = 0L;
7918 }
7919
7920 /* Those two tests are important. They define how the driver
7921 * will have to handle the data */
7922 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
7923 ((get_priv_size(priv_args[k].set_args) + offset) <= IFNAMSIZ)) {
7924 /* First case : all SET args fit within wrq */
7925 if (offset)
7926 wdata.mode = subcmd;
7927 memcpy(wdata.name + offset, buffer, IFNAMSIZ - offset);
7928 } else {
7929 if ((priv_args[k].set_args == 0) &&
7930 (priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
7931 (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ)) {
7932 /* Second case : no SET args, GET args fit within wrq */
7933 if (offset)
7934 wdata.mode = subcmd;
7935 } else {
7936 /* Third case : args won't fit in wrq, or variable number of args */
7937 if (copy_to_user(wdata.data.pointer, buffer, buffer_len)) {
7938 err = -EFAULT;
7939 goto exit;
7940 }
7941 wdata.data.flags = subcmd;
7942 }
7943 }
7944
7945 kfree(input);
7946 input = NULL;
7947
7948 extra_size = 0;
7949 if (IW_IS_SET(priv_args[k].cmd)) {
7950 /* Size of set arguments */
7951 extra_size = get_priv_size(priv_args[k].set_args);
7952
7953 /* Does it fits in iwr ? */
7954 if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
7955 ((extra_size + offset) <= IFNAMSIZ))
7956 extra_size = 0;
7957 } else {
7958 /* Size of get arguments */
7959 extra_size = get_priv_size(priv_args[k].get_args);
7960
7961 /* Does it fits in iwr ? */
7962 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
7963 (extra_size <= IFNAMSIZ))
7964 extra_size = 0;
7965 }
7966
7967 if (extra_size == 0) {
7968 extra = (u8 *)&wdata;
7969 kfree(buffer);
7970 buffer = NULL;
7971 } else {
7972 extra = buffer;
7973 }
7974
7975 handler = priv[priv_args[k].cmd - SIOCIWFIRSTPRIV];
7976 err = handler(dev, NULL, &wdata, extra);
7977
7978 /* If we have to get some data */
7979 if ((priv_args[k].get_args & IW_PRIV_TYPE_MASK) &&
7980 (priv_args[k].get_args & IW_PRIV_SIZE_MASK)) {
7981 int j;
7982 int n = 0; /* number of args */
7983 u8 str[20] = {0};
7984
7985 /* Check where is the returned data */
7986 if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
7987 (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ))
7988 n = priv_args[k].get_args & IW_PRIV_SIZE_MASK;
7989 else
7990 n = wdata.data.length;
7991
7992 output = rtw_zmalloc(4096);
7993 if (NULL == output) {
7994 err = -ENOMEM;
7995 goto exit;
7996 }
7997 switch (priv_args[k].get_args & IW_PRIV_TYPE_MASK) {
7998 case IW_PRIV_TYPE_BYTE:
7999 /* Display args */
8000 for (j = 0; j < n; j++) {
8001 sprintf(str, "%d ", extra[j]);
8002 len = strlen(str);
8003 output_len = strlen(output);
8004 if ((output_len + len + 1) > 4096) {
8005 err = -E2BIG;
8006 goto exit;
8007 }
8008 memcpy(output+output_len, str, len);
8009 }
8010 break;
8011 case IW_PRIV_TYPE_INT:
8012 /* Display args */
8013 for (j = 0; j < n; j++) {
8014 sprintf(str, "%d ", ((__s32 *)extra)[j]);
8015 len = strlen(str);
8016 output_len = strlen(output);
8017 if ((output_len + len + 1) > 4096) {
8018 err = -E2BIG;
8019 goto exit;
8020 }
8021 memcpy(output+output_len, str, len);
8022 }
8023 break;
8024 case IW_PRIV_TYPE_CHAR:
8025 /* Display args */
8026 memcpy(output, extra, n);
8027 break;
8028 default:
8029 DBG_88E("%s: Not yet implemented...\n", __func__);
8030 err = -1;
8031 goto exit;
8032 }
8033
8034 output_len = strlen(output) + 1;
8035 wrq_data->data.length = output_len;
8036 if (copy_to_user(wrq_data->data.pointer, output, output_len)) {
8037 err = -EFAULT;
8038 goto exit;
8039 }
8040 } else {
8041 /* if args to set */
8042 wrq_data->data.length = 0;
8043 }
8044
8045 exit:
8046 kfree(input);
8047 kfree(buffer);
8048 kfree(output);
8049 return err;
8050 }
8051
8052 #include <rtw_android.h>
8053 int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
8054 {
8055 struct iwreq *wrq = (struct iwreq *)rq;
8056 int ret = 0;
8057
8058 switch (cmd) {
8059 case RTL_IOCTL_WPA_SUPPLICANT:
8060 ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
8061 break;
8062 #ifdef CONFIG_88EU_AP_MODE
8063 case RTL_IOCTL_HOSTAPD:
8064 ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
8065 break;
8066 #endif /* CONFIG_88EU_AP_MODE */
8067 case SIOCDEVPRIVATE:
8068 ret = rtw_ioctl_wext_private(dev, &wrq->u);
8069 break;
8070 case (SIOCDEVPRIVATE+1):
8071 ret = rtw_android_priv_cmd(dev, rq, cmd);
8072 break;
8073 default:
8074 ret = -EOPNOTSUPP;
8075 break;
8076 }
8077 return ret;
8078 }
This page took 0.206556 seconds and 6 git commands to generate.