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